Skip to content

Commit faa6619

Browse files
Constrain UDDSketch struct members to valid ranges
1 parent 5b245c5 commit faa6619

File tree

2 files changed

+21
-19
lines changed

2 files changed

+21
-19
lines changed

crates/udd-sketch/src/lib.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::SketchHashKey::Zero;
1010
use ordered_float::OrderedFloat;
1111
#[cfg(test)]
1212
use std::collections::HashSet;
13+
use std::num::NonZeroU32;
1314

1415
#[cfg(test)]
1516
extern crate quickcheck;
@@ -59,7 +60,7 @@ impl std::cmp::PartialOrd for SketchHashKey {
5960
pub struct UDDSketchMetadata {
6061
pub max_buckets: u32,
6162
pub current_error: f64,
62-
pub compactions: u32,
63+
pub compactions: u8,
6364
pub values: u64,
6465
pub sum: f64,
6566
pub buckets: u32,
@@ -260,21 +261,21 @@ pub struct UDDSketch {
260261
buckets: SketchHashMap,
261262
alpha: f64,
262263
gamma: f64,
263-
compactions: u32, // should always be smaller than 64
264-
max_buckets: u64,
264+
compactions: u8, // should always be smaller than 64
265+
max_buckets: NonZeroU32,
265266
num_values: u64,
266267
values_sum: f64,
267268
}
268269

269270
impl UDDSketch {
270-
pub fn new(max_buckets: u64, initial_error: f64) -> Self {
271+
pub fn new(max_buckets: u32, initial_error: f64) -> Self {
271272
assert!((1e-12..1.0).contains(&initial_error));
272273
UDDSketch {
273274
buckets: SketchHashMap::new(),
274275
alpha: initial_error,
275276
gamma: (1.0 + initial_error) / (1.0 - initial_error),
276277
compactions: 0,
277-
max_buckets,
278+
max_buckets: NonZeroU32::new(max_buckets as u32).expect("max buckets should be greater than zero"),
278279
num_values: 0,
279280
values_sum: 0.0,
280281
}
@@ -291,8 +292,8 @@ impl UDDSketch {
291292
buckets: SketchHashMap::with_capacity(capacity),
292293
alpha: metadata.current_error,
293294
gamma: gamma(metadata.current_error),
294-
compactions: metadata.compactions,
295-
max_buckets: metadata.max_buckets as u64,
295+
compactions: u8::try_from(metadata.compactions).expect("compactions cannot be higher than 65"),
296+
max_buckets: NonZeroU32::new(metadata.max_buckets).expect("max buckets should be greater than zero"),
296297
num_values: metadata.values,
297298
values_sum: metadata.sum,
298299
};
@@ -329,7 +330,7 @@ impl UDDSketch {
329330
pub fn add_value(&mut self, value: f64) {
330331
self.buckets.increment(self.key(value));
331332

332-
while self.buckets.len() > self.max_buckets as usize {
333+
while self.buckets.len() > self.max_buckets.get() as usize {
333334
self.compact_buckets();
334335
}
335336

@@ -356,7 +357,7 @@ impl UDDSketch {
356357
.abs()
357358
< 1e-9 // f64::EPSILON too small, see issue #396
358359
);
359-
debug_assert_eq!(self.max_buckets, other.max_buckets as u64);
360+
debug_assert_eq!(self.max_buckets.get(), other.max_buckets);
360361

361362
if other.values == 0 {
362363
return;
@@ -375,7 +376,7 @@ impl UDDSketch {
375376
self.buckets.entry_upsert(key, count);
376377
}
377378

378-
while self.buckets.len() > self.max_buckets as usize {
379+
while self.buckets.len() > self.max_buckets.get() as usize {
379380
self.compact_buckets();
380381
}
381382

@@ -419,19 +420,19 @@ impl UDDSketch {
419420
self.buckets.entry_upsert(key, value);
420421
}
421422

422-
while self.buckets.len() > self.max_buckets as usize {
423+
while self.buckets.len() > self.max_buckets.get() as usize {
423424
self.compact_buckets();
424425
}
425426

426427
self.num_values += other.num_values;
427428
self.values_sum += other.values_sum;
428429
}
429430

430-
pub fn max_allowed_buckets(&self) -> u64 {
431-
self.max_buckets
431+
pub fn max_allowed_buckets(&self) -> u32 {
432+
self.max_buckets.get()
432433
}
433434

434-
pub fn times_compacted(&self) -> u32 {
435+
pub fn times_compacted(&self) -> u8 {
435436
self.compactions
436437
}
437438

@@ -627,7 +628,7 @@ mod tests {
627628
}
628629

629630
let metadata = UDDSketchMetadata {
630-
max_buckets: other.max_buckets as u32,
631+
max_buckets: other.max_buckets.get(),
631632
current_error: other.alpha,
632633
compactions: other.compactions,
633634
values: other.num_values,

extension/src/uddsketch.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ pub fn uddsketch_trans_inner(
3535
value: Option<f64>,
3636
fcinfo: pg_sys::FunctionCallInfo,
3737
) -> Option<Inner<UddSketchInternal>> {
38+
let max_size = u32::try_from(size).unwrap_or(PERCENTILE_AGG_DEFAULT_SIZE);
3839
unsafe {
3940
in_aggregate_context(fcinfo, || {
4041
let value = match value {
4142
None => return state,
4243
Some(value) => value,
4344
};
4445
let mut state = match state {
45-
None => UddSketchInternal::new(size as u64, max_error).into(),
46+
None => UddSketchInternal::new(max_size, max_error).into(),
4647
Some(state) => state,
4748
};
4849
state.add_value(value);
@@ -137,7 +138,7 @@ impl From<&UddSketchInternal> for SerializedUddSketch {
137138
alpha: sketch.max_error(),
138139
max_buckets: sketch.max_allowed_buckets() as u32,
139140
num_buckets: sketch.current_buckets_count() as u32,
140-
compactions: sketch.times_compacted(),
141+
compactions: u32::from(sketch.times_compacted()),
141142
count: sketch.count(),
142143
sum: sketch.sum(),
143144
buckets,
@@ -151,7 +152,7 @@ impl From<SerializedUddSketch> for UddSketchInternal {
151152
&UDDSketchMetadata {
152153
max_buckets: sketch.max_buckets,
153154
current_error: sketch.alpha,
154-
compactions: sketch.compactions,
155+
compactions: u8::try_from(sketch.compactions).expect("compactions cannot be higher than 65"),
155156
values: sketch.count,
156157
sum: sketch.sum,
157158
buckets: sketch.num_buckets,
@@ -311,7 +312,7 @@ impl<'input> UddSketch<'input> {
311312
UDDSketchMetadata {
312313
max_buckets: self.max_buckets,
313314
current_error: self.alpha,
314-
compactions: self.compactions as u32,
315+
compactions: u8::try_from(self.compactions).expect("compactions cannot be higher than 65"),
315316
values: self.count,
316317
sum: self.sum,
317318
buckets: self.num_buckets,

0 commit comments

Comments
 (0)