mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Restrict sample values of the Laplace distribution to int64_t.
This helps avoid undefined behavior from casting big double values to int64_t. Fixes #14090.
This commit is contained in:
parent
3668a4126e
commit
45bc5a0743
4
changes/bug14090
Normal file
4
changes/bug14090
Normal file
@ -0,0 +1,4 @@
|
||||
o Minor bugfixes:
|
||||
- Avoid undefined behavior when sampling huge values from the
|
||||
Laplace distribution. This made unittests fail on Raspberry Pi.
|
||||
Bug found by Device. Fixes bug 14090; bugfix on 0.2.6.2-alpha.
|
@ -527,15 +527,25 @@ round_int64_to_next_multiple_of(int64_t number, int64_t divisor)
|
||||
|
||||
/** Transform a random value <b>p</b> from the uniform distribution in
|
||||
* [0.0, 1.0[ into a Laplace distributed value with location parameter
|
||||
* <b>mu</b> and scale parameter <b>b</b> in [-Inf, Inf[. */
|
||||
double
|
||||
* <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
|
||||
* to be an integer in [INT64_MIN, INT64_MAX]. */
|
||||
int64_t
|
||||
sample_laplace_distribution(double mu, double b, double p)
|
||||
{
|
||||
double result;
|
||||
|
||||
tor_assert(p >= 0.0 && p < 1.0);
|
||||
/* This is the "inverse cumulative distribution function" from:
|
||||
* http://en.wikipedia.org/wiki/Laplace_distribution */
|
||||
return mu - b * (p > 0.5 ? 1.0 : -1.0)
|
||||
* tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
|
||||
result = mu - b * (p > 0.5 ? 1.0 : -1.0)
|
||||
* tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
|
||||
|
||||
if (result >= INT64_MAX)
|
||||
return INT64_MAX;
|
||||
else if (result <= INT64_MIN)
|
||||
return INT64_MIN;
|
||||
else
|
||||
return (int64_t) result;
|
||||
}
|
||||
|
||||
/** Add random noise between INT64_MIN and INT64_MAX coming from a
|
||||
@ -546,10 +556,10 @@ int64_t
|
||||
add_laplace_noise(int64_t signal, double random, double delta_f,
|
||||
double epsilon)
|
||||
{
|
||||
/* cast to int64_t intended */
|
||||
int64_t noise = sample_laplace_distribution(
|
||||
0.0, /* just add noise, no further signal */
|
||||
delta_f / epsilon, random);
|
||||
|
||||
if (noise > 0 && INT64_MAX - noise < signal)
|
||||
return INT64_MAX;
|
||||
else if (noise < 0 && INT64_MIN - noise > signal)
|
||||
|
@ -173,7 +173,7 @@ unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
|
||||
uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
|
||||
uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
|
||||
int64_t round_int64_to_next_multiple_of(int64_t number, int64_t divisor);
|
||||
double sample_laplace_distribution(double mu, double b, double p);
|
||||
int64_t sample_laplace_distribution(double mu, double b, double p);
|
||||
int64_t add_laplace_noise(int64_t signal, double random, double delta_f,
|
||||
double epsilon);
|
||||
int n_bits_set_u8(uint8_t v);
|
||||
|
@ -4654,11 +4654,11 @@ test_util_laplace(void *arg)
|
||||
const double delta_f = 15.0, epsilon = 0.3; /* b = 15.0 / 0.3 = 50.0 */
|
||||
(void)arg;
|
||||
|
||||
tt_assert(isinf(sample_laplace_distribution(mu, b, 0.0)));
|
||||
test_feq(-69.88855213, sample_laplace_distribution(mu, b, 0.01));
|
||||
test_feq(24.0, sample_laplace_distribution(mu, b, 0.5));
|
||||
test_feq(24.48486498, sample_laplace_distribution(mu, b, 0.51));
|
||||
test_feq(117.88855213, sample_laplace_distribution(mu, b, 0.99));
|
||||
tt_int_op(INT64_MIN, ==, sample_laplace_distribution(mu, b, 0.0));
|
||||
tt_int_op(-69, ==, sample_laplace_distribution(mu, b, 0.01));
|
||||
tt_int_op(24, ==, sample_laplace_distribution(mu, b, 0.5));
|
||||
tt_int_op(24, ==, sample_laplace_distribution(mu, b, 0.51));
|
||||
tt_int_op(117, ==, sample_laplace_distribution(mu, b, 0.99));
|
||||
|
||||
/* >>> laplace.ppf([0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99],
|
||||
* ... loc = 0, scale = 50)
|
||||
|
Loading…
Reference in New Issue
Block a user