expressions: Convert SYSMIS into int as INT_MIN during optimization too.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 10 Apr 2022 15:47:00 +0000 (08:47 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 10 Apr 2022 15:47:00 +0000 (08:47 -0700)
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
src/language/expressions/optimize.c

index d700c46fff06bdbcee598a721fb4462178bd83ea..50e1f4d1c9518d5e41c1a8f5fe8a22dfbe890e41 100644 (file)
@@ -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:
index 7d683d0181f55d5dcff4355eaadc0d4548d76c5f..129dbc30e65056f8164ba0dae78812fe4fe0f60e 100644 (file)
@@ -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)
 {