Skip to content

Commit 2aaac07

Browse files
authored
GH-50210: [C++][Gandiva] Replace precompiled std::string to fix _Unwind_Resume JIT failure on JNI builds (#50214)
### Rationale for this change See issue #50210. Two JNI CI jobs fail in `gandiva-projector-test` and `gandiva-projector-test-static` with ```bash [ RUN ] TestProjector.TestCastBitFunction JIT session error: Symbols not found: [ _Unwind_Resume ] /arrow/cpp/src/gandiva/tests/projector_test.cc:1978: Failure ``` then a _Segmentation fault_. Recent commit 4b64398 introduced a few `std::string` error messages into Gandiva precompiled functions. These are JIT-compiled to LLVM bitcode, and `std::string` pulls in `_Unwind_Resume` into bitcode even on error branches never taken. The JNI build uses [ARROW_GANDIVA_STATIC_LIBSTDCPP="ON"](https://github.com/apache/arrow/actions/runs/27745137529/job/82081554816?pr=50214#step:7:644) (_Include `-static-libstdc++ -static-libgcc...` when linking with Gandiva libraries._), so `_Unwind_Resume` is not exposed for the JIT to resolve. ### What changes are included in this PR? Replace `std::string` in precompiled functions with `snprintf` (bounded by buffer size, cannot overflow regardless of input length). ### Are these changes tested? Yes, pass on fork CI: [JNI ubuntu-latest amd64](https://github.com/tadeja/arrow/actions/runs/27724218930/job/82018788632#step:7:14558) [JNI ubuntu-24.04-arm arm64/v8](https://github.com/tadeja/arrow/actions/runs/27724218930/job/82018788669#step:7:14868) ### Are there any user-facing changes? No. * GitHub Issue: #50210 Authored-by: Tadeja Kadunc <tadeja.kadunc@gmail.com> Signed-off-by: Sutou Kouhei <kou@clear-code.com>
1 parent 924ee2f commit 2aaac07

2 files changed

Lines changed: 27 additions & 20 deletions

File tree

cpp/src/gandiva/precompiled/string_ops.cc

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -572,10 +572,12 @@ gdv_boolean castBIT_utf8(gdv_int64 context, const char* data, gdv_int32 data_len
572572
if (compare_lower_strings("false", 5, trimmed_data, trimmed_len)) return false;
573573
}
574574
// if no 'true', 'false', '0' or '1' value is found, set an error
575-
std::string err_msg = "CAST_BIT: Invalid value for boolean: '" +
576-
std::string(data, data_len) +
577-
"' (expected 0, 1, true, false; case-insensitive)";
578-
gdv_fn_context_set_error_msg(context, err_msg.c_str());
575+
char err_msg[128];
576+
snprintf(err_msg, sizeof(err_msg),
577+
"CAST_BIT: Invalid value for boolean: '%.*s'"
578+
" (expected 0, 1, true, false; case-insensitive)",
579+
data_len, data);
580+
gdv_fn_context_set_error_msg(context, err_msg);
579581
return false;
580582
}
581583

@@ -2410,31 +2412,35 @@ const char* binary_string(gdv_int64 context, const char* text, gdv_int32 text_le
24102412
OUT_TYPE next = result * 16 - digit; \
24112413
\
24122414
if (next > result) { \
2413-
std::string err_msg = \
2414-
"CAST_" #TYPE_NAME \
2415-
"_FROM_HEX: integer overflow while reading hex value '" + \
2416-
std::string(in_original, in_len_original) + "'"; \
2417-
gdv_fn_context_set_error_msg(context, err_msg.c_str()); \
2415+
char err_msg[128]; \
2416+
snprintf(err_msg, sizeof(err_msg), \
2417+
"CAST_" #TYPE_NAME \
2418+
"_FROM_HEX: integer overflow while reading hex value '%.*s'", \
2419+
in_len_original, in_original); \
2420+
gdv_fn_context_set_error_msg(context, err_msg); \
24182421
return -1; \
24192422
} \
24202423
result = next; \
24212424
read_index++; \
24222425
} else { \
2423-
std::string err_msg = "CAST_" #TYPE_NAME \
2424-
"_FROM_HEX: invalid character in hex value '" + \
2425-
std::string(in_original, in_len_original) + "'"; \
2426-
gdv_fn_context_set_error_msg(context, err_msg.c_str()); \
2426+
char err_msg[128]; \
2427+
snprintf(err_msg, sizeof(err_msg), \
2428+
"CAST_" #TYPE_NAME "_FROM_HEX: invalid character in hex value '%.*s'", \
2429+
in_len_original, in_original); \
2430+
gdv_fn_context_set_error_msg(context, err_msg); \
24272431
return -1; \
24282432
} \
24292433
} \
24302434
if (!negative) { \
24312435
result *= -1; \
24322436
\
24332437
if (result < 0) { \
2434-
std::string err_msg = "CAST_" #TYPE_NAME \
2435-
"_FROM_HEX: integer overflow while reading hex value '" + \
2436-
std::string(in_original, in_len_original) + "'"; \
2437-
gdv_fn_context_set_error_msg(context, err_msg.c_str()); \
2438+
char err_msg[128]; \
2439+
snprintf(err_msg, sizeof(err_msg), \
2440+
"CAST_" #TYPE_NAME \
2441+
"_FROM_HEX: integer overflow while reading hex value '%.*s'", \
2442+
in_len_original, in_original); \
2443+
gdv_fn_context_set_error_msg(context, err_msg); \
24382444
return -1; \
24392445
} \
24402446
} \

cpp/src/gandiva/precompiled/time.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,10 @@ static const int WEEK_LEN[] = {6, 6, 7, 9, 8, 6, 8};
270270
} \
271271
} \
272272
if (dateSearch == 0) { \
273-
std::string err_msg = "NEXT_DAY: '" + std::string(in, in_len) + \
274-
"' is not a recognized day of the week"; \
275-
gdv_fn_context_set_error_msg(context, err_msg.c_str()); \
273+
char err_msg[128]; \
274+
snprintf(err_msg, sizeof(err_msg), \
275+
"NEXT_DAY: '%.*s' is not a recognized day of the week", in_len, in); \
276+
gdv_fn_context_set_error_msg(context, err_msg); \
276277
return 0; \
277278
} \
278279
\

0 commit comments

Comments
 (0)