google / google/googlesql

`RoundUpToNextPowerOfTwo` overflows on targets where `long` is 32-bit

Open Beginner friendly
#171 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
2.6k
Forks
260
PR merge metrics
No merged PRs in 30d

Description

`RoundUpToNextPowerOfTwo` in `googlesql/public/types/internal_utils.h` uses `1L << 62` for both its range guard and its clamp value.

`1L` has type `long`, and wherever `long` is 32 bits the shift count exceeds the type width — undefined behaviour. That covers:

- all ILP32 targets: wasm32 (emscripten), 32-bit ARM, x86-32;
- 64-bit Windows, whose LLP64 data model keeps `long` at 32 bits.

Observed under wasm32-emscripten: the guard misfires for ordinary small inputs, logging `Out of range: 2` repeatedly during every analyzer run and returning a garbage "rounded" value.

The function feeds only `GetRawHashSetCapacityEstimateFromExpectedSize`, so analysis *results* are unaffected, but the hash-set memory-usage estimates are wrong on 32-bit and the ERROR logs are noise.

Possible fix:

```patch
From 08ff5eeb982d691cfb40e735cf233f8bdb661be4 Mon Sep 17 00:00:00 2001
From: Fredrik Fornwall
Date: Thu, 23 Jul 2026 01:27:22 +0200
Subject: [PATCH] Fix RoundUpToNextPowerOfTwo overflow on targets where long is
32-bit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

RoundUpToNextPowerOfTwo in googlesql/public/types/internal_utils.h
computes its range guard and clamp value as `1L << 62`. The literal
`1L` has type `long`, and on any target where `long` is 32 bits the
shift count exceeds the type width, which is undefined behaviour.
That covers all ILP32 targets — wasm32 (emscripten), 32-bit ARM,
x86-32 — and also 64-bit Windows, whose LLP64 data model keeps
`long` at 32 bits even though pointers are 64-bit.

Observed under wasm32-emscripten: the guard misfires for ordinary
small inputs, logging "Out of range: 2" on every analyzer run and
returning a garbage rounded value. The function only feeds
GetRawHashSetCapacityEstimateFromExpectedSize, so analysis results
are unaffected, but hash-set memory-usage estimates are wrong and
the ERROR logs are noise.

Use `int64_t{1} << 62` for both the mask and the clamp, which is
identical to the old behaviour on LP64 and correct everywhere else.

Signed-off-by: Fredrik Fornwall
---
googlesql/public/types/internal_utils.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/googlesql/public/types/internal_utils.h b/googlesql/public/types/internal_utils.h
index ad8efed28..5fe3c135f 100644
--- a/googlesql/public/types/internal_utils.h
+++ b/googlesql/public/types/internal_utils.h
@@ -78,10 +78,10 @@ static size_t GetArrayAllocationMemoryEstimate(size_t elements_count) {

// Rounds up the capacity to the next power of 2
inline int64_t RoundUpToNextPowerOfTwo(int64_t n) {
- if (n < 0 || (n & (1L << 62)) != 0) {
+ if (n < 0 || (n & (int64_t{1} << 62)) != 0) {
ABSL_LOG(ERROR) << "Out of range: " << n;
// Restrict to the valid range.
- return n < 0 ? 1 : 1L << 62;
+ return n < 0 ? 1 : int64_t{1} << 62;
}

int64_t power = 1;
```

Contributor guide

Open the contributing guide

Research direction

Start in googlesql/public/types/internal_utils.h at RoundUpToNextPowerOfTwo and trace its use by GetRawHashSetCapacityEstimateFromExpectedSize. Run an analyzer build on a 32-bit target or wasm32-emscripten and confirm ordinary inputs no longer produce out-of-range errors or incorrect hash-set memory estimates.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
90/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.