Fix incorrect zero extension of Datum in JIT tuple deform code
authorDavid Rowley <[email protected]>
Thu, 23 Oct 2025 00:11:02 +0000 (13:11 +1300)
committerDavid Rowley <[email protected]>
Thu, 23 Oct 2025 00:11:02 +0000 (13:11 +1300)
When JIT deformed tuples (controlled via the jit_tuple_deforming GUC),
types narrower than sizeof(Datum) would be zero-extended up to Datum
width.  This wasn't the same as what fetch_att() does in the standard
tuple deforming code.  Logically the values are the same when fetching
via the DatumGet*() marcos, but negative numbers are not the same in
binary form.

In the report, the problem was manifesting itself with:

ERROR: could not find memoization table entry

in a query which had a "Cache Mode: binary" Memoize node. However, it's
currently unclear what else is affected.  Anything that uses
datum_image_eq() or datum_image_hash() on a Datum from a tuple deformed by
JIT could be affected, but it may not be limited to that.

The fix for this is simple: use signed extension instead of zero
extension.

Many thanks to Emmanuel Touzery for reporting this issue and providing
steps and backup which allowed the problem to easily be recreated.

Reported-by: Emmanuel Touzery <[email protected]>
Author: David Rowley <[email protected]>
Discussion: https://postgr.es/m/DB8P194MB08532256D5BAF894F241C06393F3A@DB8P194MB0853.EURP194.PROD.OUTLOOK.COM
Backpatch-through: 13

src/backend/jit/llvm/llvmjit_deform.c

index 9791073faf9d3387908f0b50a3c7f22189525ac5..f500cbda893ef20f2c0b67558d7d66786c0f4a3f 100644 (file)
@@ -663,7 +663,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
            v_tmp_loaddata =
                LLVMBuildPointerCast(b, v_attdatap, vartypep, "");
            v_tmp_loaddata = l_load(b, vartype, v_tmp_loaddata, "attr_byval");
-           v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, TypeDatum, "");
+           v_tmp_loaddata = LLVMBuildSExt(b, v_tmp_loaddata, TypeDatum, "");
 
            LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
        }