aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2024-02-25 21:30:33 +0000
committerdrh <>2024-02-25 21:30:33 +0000
commitdfd991c3b947f3d746ee56ba3295acd8074eead2 (patch)
tree201a120b4a37feeb34f5ec017b5e28aee68325b4 /src
parent7598e7d70e30d963b172ef5902e2e51cf161fef5 (diff)
downloadsqlite-dfd991c3b947f3d746ee56ba3295acd8074eead2.tar.gz
sqlite-dfd991c3b947f3d746ee56ba3295acd8074eead2.zip
Make sure key comprisons are done correctly if the index key contains NaN
values that have not been shifted into NULLs. That can only happen due to database corruption, but we need to deal with it nevertheless. FossilOrigin-Name: 7e4c743f9e6ef33500795543e6db9a77c533025bf00c2ee97abd433a3871b5a1
Diffstat (limited to 'src')
-rw-r--r--src/vdbeaux.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 420365e93..fe0dbd6b0 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -4060,6 +4060,23 @@ static void serialGet(
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
}
}
+static int serialGet7(
+ const unsigned char *buf, /* Buffer to deserialize from */
+ Mem *pMem /* Memory cell to write value into */
+){
+ u64 x = FOUR_BYTE_UINT(buf);
+ u32 y = FOUR_BYTE_UINT(buf+4);
+ x = (x<<32) + y;
+ assert( sizeof(x)==8 && sizeof(pMem->u.r)==8 );
+ swapMixedEndianFloat(x);
+ memcpy(&pMem->u.r, &x, sizeof(x));
+ if( IsNaN(x) ){
+ pMem->flags = MEM_Null;
+ return 1;
+ }
+ pMem->flags = MEM_Real;
+ return 0;
+}
void sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
@@ -4739,7 +4756,7 @@ int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else if( serial_type==7 ){
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+ serialGet7(&aKey1[d1], &mem1);
rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
}else{
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
@@ -4764,14 +4781,18 @@ int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else{
- sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( serial_type==7 ){
- if( mem1.u.r<pRhs->u.r ){
+ if( serialGet7(&aKey1[d1], &mem1) ){
+ rc = -1; /* mem1 is a NaN */
+ }else if( mem1.u.r<pRhs->u.r ){
rc = -1;
}else if( mem1.u.r>pRhs->u.r ){
rc = +1;
+ }else{
+ assert( rc==0 );
}
}else{
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
}
}
@@ -4841,7 +4862,14 @@ int sqlite3VdbeRecordCompareWithSkip(
/* RHS is null */
else{
serial_type = aKey1[idx1];
- rc = (serial_type!=0 && serial_type!=10);
+ if( serial_type==0
+ || serial_type==10
+ || (serial_type==7 && serialGet7(&aKey1[d1], &mem1)!=0)
+ ){
+ assert( rc==0 );
+ }else{
+ rc = 1;
+ }
}
if( rc!=0 ){