From: Ben Pfaff Date: Sun, 10 Apr 2022 15:47:00 +0000 (-0700) Subject: expressions: Convert SYSMIS into int as INT_MIN during optimization too. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=435b06ea1e6cefd2d540552e161a84a9b2cbef42 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. --- 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) {