Repository navigation
fix: Avoid implicit 64-to-32-bit conversions on 32-bit platforms - #983
Conversation
Building with -Wconversion on 32-bit targets (e.g. armv7 Android in the vcpkg CI) fails because several int64_t values are passed to functions that take size_t (memcpy, memset, snprintf, malloc, fread and flatcc builder helpers). Cast these explicitly. Closes apache#797.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #983 +/- ##
==========================================
- Coverage 78.59% 78.58% -0.02%
==========================================
Files 106 106
Lines 17153 17173 +20
Branches 2043 2045 +2
==========================================
+ Hits 13482 13495 +13
- Misses 2422 2427 +5
- Partials 1249 1251 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
paleolimbot
left a comment
There was a problem hiding this comment.
Thank you! It has always bothered me that this emits warnings with -Wconversion.
I know we don't do this everywhere, but we should check these, at least in debug builds. Perhaps you can add something like
static inline size_t _ArrowInt64ToSizeT(int64_t x) {
NANOARROW_DCHECK(x < (int64_t)SIZE_T_MAX);
return (size_t)x
}...to types_inline.h and wrap these conversions. I believe all of these are safe as DCHECKs (the only place we would want to check and return an error is where the input could come from a user input, either via a high level binding or an IPC file). I believe most of these would surface as allocation failures before the cast.
| void* ArrowMalloc(int64_t size) { return malloc((size_t)size); } | ||
|
|
||
| void* ArrowRealloc(void* ptr, int64_t size) { return realloc(ptr, size); } | ||
| void* ArrowRealloc(void* ptr, int64_t size) { return realloc(ptr, (size_t)size); } |
There was a problem hiding this comment.
I think these conversions should be checked (and return null on failure), cleaning up the pointer in the realloc case
| NANOARROW_ASSERT_OK( | ||
| ArrowIpcEncoderWriteContinuationAndSize(out, (size_t)padded_size)); |
There was a problem hiding this comment.
We should check the padded size here (or update ArrowIpcEncoderWriteContinuationAndSize() to accept an int64 and check the failure code)
| memcpy(buf, private_data->input.data + private_data->cursor_bytes, | ||
| (size_t)bytes_to_read); |
There was a problem hiding this comment.
I think this can be a NANOARROW_DCHECK that bytes_to_read is small enough (there shouldn't have been a single in memory buffer bigger than 4 GB in the process anyway)
| int64_t bytes_read = | ||
| (int64_t)fread(buf, 1, (size_t)buf_size_bytes, private_data->file_ptr); |
There was a problem hiding this comment.
I think here we can also NANOARROW_DCHECK (because the output can't have been allocated to a size bigger than 4 GB in a 32 bit process)
| int64_t bytes_written = | ||
| (int64_t)fwrite(buf, 1, (size_t)buf_size_bytes, private_data->file_ptr); |
There was a problem hiding this comment.
I think a DCHECK would be good here too
…here input-derived Add _ArrowInt64FitsInSizeT()/_ArrowInt64ToSizeT() to inline_types.h and use them for the conversions touched in this PR. ArrowMalloc()/ArrowRealloc() return NULL (freeing the pointer in the realloc case) for sizes that do not fit in size_t, the IPC encoder checks the padded message size instead of asserting, and the stream reader returns EINVAL if the header size is out of range.
|
Thanks @paleolimbot. 487d8a9 adds The places you asked to check for real:
I ran a Debug build ( |
|
Thank you! It looks like CI has a few complaints, but once those are resolved I think this is good to go. |
|
Thanks @paleolimbot! I looked at the two failing jobs:
Let me know if you see anything in the diff itself that needs changing. (AI-assisted reply.) |
|
Thanks! I hadn't noticed, but I've put up a PR to fix that and will sort through it this weekend. Thank you! |
Closes #797.
Building nanoarrow with
-Wconversionon a 32-bit target (the armv7 Android build in the vcpkg CI from the issue) fails with-Wshorten-64-to-32errors, because a number ofint64_tsizes are passed straight to functions that takesize_t:memcpy/memset/memmove,snprintf,malloc/realloc,fread/fwrite,strncmp, and the flatcc builder/vector helpers.This adds explicit
(size_t)casts at those call sites incommon/,device/device.candipc/. There's no behaviour change on 64-bit platforms. InArrowArrayViewCompareBuffer()thesize_bytes > 0check stays on the signed value and only the length handed tomemcmp()is converted, so the stringified comparison message the tests check doesn't change.Testing
clang -m32 -std=gnu99 -fsyntax-only -Wall -Wextra -Wpedantic -Wconversion -Wno-sign-conversion(clang 19, i386) oversrc/nanoarrow/common/*.c,device/device.candipc/{codecs,decoder,encoder,reader,writer}.c: 40 distinct-Wshorten-64-to-32warning locations onmain, none with this change. I don't have the Android NDK setup locally, so this is a 32-bit x86 stand-in for the armv7 build.NANOARROW_BUILD_TESTS=ON NANOARROW_IPC=ON NANOARROW_DEVICE=ON:ctest422/422 passed.This PR was prepared with AI assistance; I reviewed the changes and ran the checks above.