From 435b06ea1e6cefd2d540552e161a84a9b2cbef42 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 10 Apr 2022 08:47:00 -0700 Subject: [PATCH] expressions: Convert SYSMIS into int as INT_MIN during optimization too. In an expression like LPAD('abc', $sysmis), the LPAD function is evaluated using a C function that takes an 'int' as its second argument. During expression evaluation, out-of-range values get converted into SYSMIS by the NUM_TO_INTEGER operator that gets automatically inserted to ensure that, and then SYSMIS gets converted into INT_MIN to pass to the C function. This worked OK for runtime evaluation, but the optimizer failed to do the conversion of SYSMIS to INT_MIN, which yielded undefined behavior. Some platforms (e.g. GCC on x86) converted SYSMIS (which is the second-smallest 'double' value) into INT_MIN, so no problem showed up there, but other platforms yielded INT_MAX, causing unexpected failures. This commit fixes the problem by explicitly converting SYSMIS into INT_MIN during optimization. Thanks to Friedrich Beckmann for reporting and uncovering the problem. Bug #62267. --- src/language/expressions/generate.py | 3 ++- src/language/expressions/optimize.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/language/expressions/generate.py b/src/language/expressions/generate.py index d700c46fff..50e1f4d1c9 100644 --- a/src/language/expressions/generate.py +++ b/src/language/expressions/generate.py @@ -870,7 +870,8 @@ def generate_optimize_inc(): type_ = arg.type_ c_type = type_.c_type if arg.idx is None: - func = 'get_%s_arg' % type_.atom + func = ('get_integer_arg' if type_.name == 'integer' + else 'get_%s_arg' % type_.atom) decls += ['%sarg_%s = %s (node, %s)' % (c_type, name, func, arg_idx)] else: diff --git a/src/language/expressions/optimize.c b/src/language/expressions/optimize.c index 7d683d0181..129dbc30e6 100644 --- a/src/language/expressions/optimize.c +++ b/src/language/expressions/optimize.c @@ -163,6 +163,13 @@ get_number_args (struct expr_node *n, size_t arg_idx, size_t n_args, return d; } +static int +get_integer_arg (struct expr_node *n, size_t arg_idx) +{ + double number = n->args[arg_idx]->number; + return number == SYSMIS ? INT_MIN : number; +} + static struct substring get_string_arg (struct expr_node *n, size_t arg_idx) { -- 2.30.2