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.
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:
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)
{