comdb2
comdb2 copied to clipboard
{174079549} : Fix invalid memory access in ezsystable
While executing subqueries, we sometimes end up reading free'd data.
For example, the plan below
cdb2sql> Select * from comdb2_keycomponents where tablename='t_str' and keyname=(select keyname from comdb2sys_keys where tablename='t_str' and keynumber=0) (Plan=' 0 [ Init]: Start at 38 ') (Plan=' 1 [ VOpen]: Open read cursor [0] on virtual table comdb2_keycomponents') (Plan=' 2 [ Explain]: No-op (169)') (Plan=' 3 [ Integer]: R1 = 0') (Plan=' 4 [ Integer]: R2 = 0') (Plan=' 5 [ VFilter]: ???') (Plan=' 6 [ VColumn]: R[3]=comdb2_keycomponents.tablename (cmnt:comdb2_keycomponents.tablename)') (Plan=' 7 [ Ne]: If R3 != R4 or either is NULL goto 35') (Plan=' 8 [ VColumn]: R[3]=comdb2_keycomponents.keyname (cmnt:comdb2_keycomponents.keyname)') (Plan=' 9 [ Integer]: R6 = 27 (cmnt:return address)') (Plan=' 10 [ Once]: If flag F0 is set go to 27, otherwise set it and fall through to next instruction') (Plan=' 11 [ Explain]: No-op (169)') (Plan=' 12 [ Null]: R7 = NULL (cmnt:Init subquery result)') (Plan=' 13 [ Integer]: R8 = 1 (cmnt:LIMIT counter)') (Plan=' 14 [ VOpen]: Open read cursor [1] on virtual table comdb2_keys') (Plan=' 15 [ Explain]: No-op (169)') (Plan=' 16 [ Integer]: R10 = 0') (Plan=' 17 [ Integer]: R11 = 0') (Plan=' 18 [ VFilter]: ???') (Plan=' 19 [ VColumn]: R[12]=comdb2_keys.tablename (cmnt:comdb2_keys.tablename)') (Plan=' 20 [ Ne]: If R12 != R4 or either is NULL goto 25') (Plan=' 21 [ VColumn]: R[12]=comdb2_keys.keynumber (cmnt:comdb2_keys.keynumber)') (Plan=' 22 [ Ne]: If R12 != R13 or either is NULL goto 25') (Plan=' 23 [ VColumn]: R[7]=comdb2_keys.keyname (cmnt:comdb2_keys.keyname)') (Plan=' 24 [DecrJumpZero]: R8 --; If R8 == 0 jump to 26') (Plan=' 25 [ VNext]: Move cursor [1] to next entry. If entry exists, go to 19???') (Plan=' 26 [ Close]: Close cursor [1]') (Plan=' 27 [ Return]: Jump to R6 + 1') (Plan=' 28 [ Ne]: If R3 != R7 or either is NULL goto 35') (Plan=' 29 [ VColumn]: R[14]=comdb2_keycomponents.tablename (cmnt:comdb2_keycomponents.tablename)') (Plan=' 30 [ VColumn]: R[15]=comdb2_keycomponents.keyname (cmnt:comdb2_keycomponents.keyname)') (Plan=' 31 [ VColumn]: R[16]=comdb2_keycomponents.columnnumber (cmnt:comdb2_keycomponents.columnnumber)') (Plan=' 32 [ VColumn]: R[17]=comdb2_keycomponents.columnname (cmnt:comdb2_keycomponents.columnname)') (Plan=' 33 [ VColumn]: R[18]=comdb2_keycomponents.isdescending (cmnt:comdb2_keycomponents.isdescending)') (Plan=' 34 [ ResultRow]: Row available at R14..R18') (Plan=' 35 [ VNext]: Move cursor [0] to next entry. If entry exists, go to 6???') (Plan=' 36 [ Close]: Close cursor [0]') (Plan=' 37 [ Halt]: Stop') (Plan=' 38 [ Transaction]: Start a readonly transaction (cmnt:usesStmtJournal=0)') (Plan=' 39 [ String8]: R4 = "t_str"') (Plan=' 40 [ Integer]: R13 = 0') (Plan=' 41 [ Goto]: Go to 1')
Step 28 access data retrieved from a cursor which is closed in step 26. If this data is a pointer, then the data being pointed to has already been freed as part of the cursor close method in the ezsystable code path.
Valgrind confirmed the same.
This patch fixes the issue by telling sqlite to make a copy of the data being pointed to , and store THAT in the register instead of the just the pointer.
cdb2test Mar 7 12:07:07 2024 in-comdb2db aar_ezsys_bug.R20240307.4