Skip to content

Commit 50f3850

Browse files
committed
[hdrhistogram]: Prevent an FPE in rd_hdr_histogram_new (#4949)
The Floating Point Exception (FPE) `FE_DIVBYZERO` is flagged in `rd_hdr_histogram_new` when `log2()` is called with `0`. This is done in `rd_avg_init` numerous times, some of which cannot be disabled in recent versions. Consumers of librdkakfa may enable the raising of exceptions when FPEs occur, including `FE_DIVBYZERO`, which causes the function to fail. It is reasonable for the callers of `rd_hdr_histogram_new` to pass `0` for the `minValue` parameter, and the intention of the calculation of `unitMagnitude` is also reasonable. As such, fixing the maths there is the correct approach. `unitMagnitude` being `0` in this case is an apt choice based on how log2(n) works for n near `0`, and that the caluclation already minimises to `0`. A simple test was included that resets the flags, runs the offending function, and observes the new set flags. Appropriately, it fails before the fix, and passes after.
1 parent c7649b8 commit 50f3850

File tree

6 files changed

+52
-1
lines changed

6 files changed

+52
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ librdkafka v2.12.0 is a feature release:
2121
so it's possible it did overlap with the periodic `topic.metadata.refresh.interval.ms`
2222
and cause a re-bootstrap even if not needed.
2323
Happening since 2.11.0 (#5177).
24+
* Issues: #4949: Prevent an FPE in rd_hdr_histogram_new.
2425

2526
### Telemetry fixes
2627

src/rdhdrhistogram.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ rd_hdr_histogram_t *rd_hdr_histogram_new(int64_t minValue,
8989
int64_t largestValueWithSingleUnitResolution;
9090
int32_t subBucketCountMagnitude;
9191
int32_t subBucketHalfCountMagnitude;
92+
double potentialUnitMagnitude;
9293
int32_t unitMagnitude;
9394
int32_t subBucketCount;
9495
int32_t subBucketHalfCount;
@@ -109,7 +110,8 @@ rd_hdr_histogram_t *rd_hdr_histogram_new(int64_t minValue,
109110

110111
subBucketHalfCountMagnitude = RD_MAX(subBucketCountMagnitude, 1) - 1;
111112

112-
unitMagnitude = (int32_t)RD_MAX(floor(log2((double)minValue)), 0);
113+
potentialUnitMagnitude = minValue == 0 ? 0 : log2((double)minValue);
114+
unitMagnitude = (int32_t)RD_MAX(floor(potentialUnitMagnitude), 0);
113115

114116
subBucketCount =
115117
(int32_t)pow(2, (double)subBucketHalfCountMagnitude + 1.0);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* librdkafka - Apache Kafka C library
3+
*
4+
* Copyright (c) 2025, Confluent Inc.
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*/
28+
29+
#include "test.h"
30+
#include "rdhdrhistogram.h"
31+
#include <fenv.h>
32+
33+
void do_test_rd_hdr_histogram_new_fpe() {
34+
rd_hdr_histogram_t *hist;
35+
feclearexcept(FE_ALL_EXCEPT);
36+
hist = rd_hdr_histogram_new(0, 10000, 2);
37+
TEST_ASSERT(fetestexcept(FE_DIVBYZERO) == 0, "Division by zero occurred");
38+
rd_hdr_histogram_destroy(hist);
39+
}
40+
41+
int main_0154_rd_hdr_histogram_new_fpe(int argc, char **argv) {
42+
do_test_rd_hdr_histogram_new_fpe();
43+
return 0;
44+
}

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ set(
143143
0151-purge-brokers.c
144144
0152-rebootstrap.c
145145
0153-memberid.c
146+
0154-rd_hdr_histogram_new-fpe.c
146147
8000-idle.cpp
147148
8001-fetch_from_follower_mock_manual.c
148149
test.c

tests/test.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ _TEST_DECL(0150_telemetry_mock);
270270
_TEST_DECL(0151_purge_brokers_mock);
271271
_TEST_DECL(0152_rebootstrap_local);
272272
_TEST_DECL(0153_memberid);
273+
_TEST_DECL(0154_rd_hdr_histogram_new_fpe);
273274

274275
/* Manual tests */
275276
_TEST_DECL(8000_idle);
@@ -536,6 +537,7 @@ struct test tests[] = {
536537
_TEST(0151_purge_brokers_mock, TEST_F_LOCAL),
537538
_TEST(0152_rebootstrap_local, TEST_F_LOCAL),
538539
_TEST(0153_memberid, 0, TEST_BRKVER(0, 4, 0, 0)),
540+
_TEST(0154_rd_hdr_histogram_new_fpe, TEST_F_LOCAL),
539541

540542

541543
/* Manual tests */

win32/tests/tests.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@
233233
<ClCompile Include="..\..\tests\0151-purge-brokers.c" />
234234
<ClCompile Include="..\..\tests\0152-rebootstrap.c" />
235235
<ClCompile Include="..\..\tests\0153-memberid.c" />
236+
<ClCompile Include="..\..\tests\0154-rd_hdr_histogram_new-fpe.c" />
236237
<ClCompile Include="..\..\tests\8000-idle.cpp" />
237238
<ClCompile Include="..\..\tests\8001-fetch_from_follower_mock_manual.c" />
238239
<ClCompile Include="..\..\tests\test.c" />

0 commit comments

Comments
 (0)