SQLite

Check-in [f10130ede4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix more instances of assuming 'char' is signed. And, make sure to never shift a signed integer.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | broken-on-arm
Files: files | file ages | folders
SHA1: f10130ede433a19b3945753f23962871c8d2dcf3
User & Date: drh 2014-03-04 04:04:33.269
Context
2014-03-04
04:12
Refactor the sqlite3VdbeRecordCompare() routine used to compare btree records. Create fast-track special case routines to handle the common cases more quickly. This gives a significant performance boost. (check-in: 3325ad5bdc user: drh tags: trunk)
04:04
Fix more instances of assuming 'char' is signed. And, make sure to never shift a signed integer. (Closed-Leaf check-in: f10130ede4 user: drh tags: broken-on-arm)
00:15
Do not assume that 'char' is signed. Make it explicit. (check-in: 979da752e6 user: drh tags: broken-on-arm)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbeaux.c.
2938
2939
2940
2941
2942
2943
2944








2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
    return len;
  }

  /* NULL or constants 0 or 1 */
  return 0;
}









/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem.  Return the number of bytes read.
*/ 
u32 sqlite3VdbeSerialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
  Mem *pMem                     /* Memory cell to write value into */
){
  u64 x;
  u32 y;
  int i;
  switch( serial_type ){
    case 10:   /* Reserved for future use */
    case 11:   /* Reserved for future use */
    case 0: {  /* NULL */
      pMem->flags = MEM_Null;
      break;
    }
    case 1: { /* 1-byte signed integer */
      pMem->u.i = (signed char)buf[0];
      pMem->flags = MEM_Int;
      return 1;
    }
    case 2: { /* 2-byte signed integer */
      i = 256*(signed char)buf[0] | buf[1];
      pMem->u.i = (i64)i;
      pMem->flags = MEM_Int;
      return 2;
    }
    case 3: { /* 3-byte signed integer */
      i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
      pMem->u.i = (i64)i;
      pMem->flags = MEM_Int;
      return 3;
    }
    case 4: { /* 4-byte signed integer */
      y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
      pMem->u.i = (i64)*(int*)&y;
      pMem->flags = MEM_Int;
      return 4;
    }
    case 5: { /* 6-byte signed integer */
      x = 256*(signed char)buf[0] + buf[1];
      y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
      x = (x<<32) | y;
      pMem->u.i = *(i64*)&x;
      pMem->flags = MEM_Int;
      return 6;
    }
    case 6:   /* 8-byte signed integer */
    case 7: { /* IEEE floating point */
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
      /* Verify that integers and floating point values use the same
      ** byte order.  Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
      ** defined that 64-bit floating point values really are mixed
      ** endian.
      */
      static const u64 t1 = ((u64)0x3ff00000)<<32;
      static const double r1 = 1.0;
      u64 t2 = t1;
      swapMixedEndianFloat(t2);
      assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
      x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
      y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
      x = (x<<32) | y;
      if( serial_type==6 ){
        pMem->u.i = *(i64*)&x;
        pMem->flags = MEM_Int;
      }else{
        assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
        swapMixedEndianFloat(x);







>
>
>
>
>
>
>
>











<








|




<
|




<
|




|





<
<
<
|

















|
|







2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976

2977
2978
2979
2980
2981

2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992



2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
    return len;
  }

  /* NULL or constants 0 or 1 */
  return 0;
}

/* Input "x" is a sequence of unsigned characters that represent a
** big-endian integer.  Return the equivalent native integer
*/
#define ONE_BYTE_INT(x)    ((i8)(x)[0])
#define TWO_BYTE_INT(x)    (256*(i8)((x)[0])|(x)[1])
#define THREE_BYTE_INT(x)  (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
#define FOUR_BYTE_UINT(x)  (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])

/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem.  Return the number of bytes read.
*/ 
u32 sqlite3VdbeSerialGet(
  const unsigned char *buf,     /* Buffer to deserialize from */
  u32 serial_type,              /* Serial type to deserialize */
  Mem *pMem                     /* Memory cell to write value into */
){
  u64 x;
  u32 y;

  switch( serial_type ){
    case 10:   /* Reserved for future use */
    case 11:   /* Reserved for future use */
    case 0: {  /* NULL */
      pMem->flags = MEM_Null;
      break;
    }
    case 1: { /* 1-byte signed integer */
      pMem->u.i = ONE_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      return 1;
    }
    case 2: { /* 2-byte signed integer */

      pMem->u.i = TWO_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      return 2;
    }
    case 3: { /* 3-byte signed integer */

      pMem->u.i = THREE_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      return 3;
    }
    case 4: { /* 4-byte signed integer */
      y = FOUR_BYTE_UINT(buf);
      pMem->u.i = (i64)*(int*)&y;
      pMem->flags = MEM_Int;
      return 4;
    }
    case 5: { /* 6-byte signed integer */



      pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
      pMem->flags = MEM_Int;
      return 6;
    }
    case 6:   /* 8-byte signed integer */
    case 7: { /* IEEE floating point */
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
      /* Verify that integers and floating point values use the same
      ** byte order.  Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
      ** defined that 64-bit floating point values really are mixed
      ** endian.
      */
      static const u64 t1 = ((u64)0x3ff00000)<<32;
      static const double r1 = 1.0;
      u64 t2 = t1;
      swapMixedEndianFloat(t2);
      assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
      x = FOUR_BYTE_UINT(buf);
      y = FOUR_BYTE_UINT(buf+4);
      x = (x<<32) | y;
      if( serial_type==6 ){
        pMem->u.i = *(i64*)&x;
        pMem->flags = MEM_Int;
      }else{
        assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
        swapMixedEndianFloat(x);
3348
3349
3350
3351
3352
3353
3354

3355
3356
3357
3358
3359
3360
3361
3362
3363
3364

3365

3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
** The first argument passed to this function is a serial-type that
** corresponds to an integer - all values between 1 and 9 inclusive 
** except 7. The second points to a buffer containing an integer value
** serialized according to serial_type. This function deserializes
** and returns the value.
*/
static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){

  assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
  switch( serial_type ){
    case 0:
    case 1:
      return (char)aKey[0];
    case 2:
      return ((char)aKey[0] << 8) | aKey[1];
    case 3:
      return ((char)aKey[0] << 16) | (aKey[1] << 8) | aKey[2];
    case 4:

      return ((char)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3];

    case 5: {
      i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
      u32 lsw = (aKey[4] << 8) | aKey[5];
      return (i64)( msw << 16 | (u64)lsw );
    }
    case 6: {
      i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
      u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7];
      return (i64)( msw << 32 | (u64)lsw );
    }
  }

  return (serial_type - 8);
}

/*







>




|

|

|
|
>
|
>

<
<
|


|
|
|







3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371


3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
** The first argument passed to this function is a serial-type that
** corresponds to an integer - all values between 1 and 9 inclusive 
** except 7. The second points to a buffer containing an integer value
** serialized according to serial_type. This function deserializes
** and returns the value.
*/
static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
  u32 y;
  assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
  switch( serial_type ){
    case 0:
    case 1:
      return ONE_BYTE_INT(aKey);
    case 2:
      return TWO_BYTE_INT(aKey);
    case 3:
      return THREE_BYTE_INT(aKey);
    case 4: {
      y = FOUR_BYTE_UINT(aKey);
      return (i64)*(int*)&y;
    }
    case 5: {


      return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
    }
    case 6: {
      u64 x = FOUR_BYTE_UINT(aKey);
      x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
      return (i64)*(i64*)&x;
    }
  }

  return (serial_type - 8);
}

/*
3574
3575
3576
3577
3578
3579
3580


3581
3582
3583
3584
3585
3586
3587
3588
3589

3590
3591
3592

3593
3594
3595

3596

3597
3598

3599
3600
3601
3602
3603
3604
3605
3606
3607

3608
3609
3610
3611
3612
3613
3614
3615
  int nKey1, const void *pKey1, /* Left key */
  const UnpackedRecord *pPKey2, /* Right key */
  int bSkip                     /* Ignored */
){
  const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
  int serial_type = ((const u8*)pKey1)[1];
  int res;


  i64 v = pPKey2->aMem[0].u.i;
  i64 lhs;
  UNUSED_PARAMETER(bSkip);

  assert( bSkip==0 );
  switch( serial_type ){
    case 1:
      lhs = (char)(aKey[0]);
      break;

    case 2:
      lhs = 256*(signed char)aKey[0] + aKey[1];
      break;

    case 3:
      lhs = 65536*(char)aKey[0] | (aKey[1]<<8) | aKey[2];
      break;

    case 4:

      lhs = (int)(((u32)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]);
      break;

    case 5: {
      i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
      u32 lsw = (aKey[4] << 8) | aKey[5];
      lhs = (i64)( msw << 16 | (u64)lsw );
      break;
    }
    case 6: {
      i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
      u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7];

      lhs = (i64)( msw << 32 | (u64)lsw );
      break;
    }
    case 8: 
      lhs = 0;
      break;
    case 9:
      lhs = 1;







>
>






|
|

>
|
|

>
|
|

>
|
>
|

>
|
<
<
|


|
|
<
>
|







3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609


3610
3611
3612
3613
3614

3615
3616
3617
3618
3619
3620
3621
3622
3623
  int nKey1, const void *pKey1, /* Left key */
  const UnpackedRecord *pPKey2, /* Right key */
  int bSkip                     /* Ignored */
){
  const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
  int serial_type = ((const u8*)pKey1)[1];
  int res;
  u32 y;
  u64 x;
  i64 v = pPKey2->aMem[0].u.i;
  i64 lhs;
  UNUSED_PARAMETER(bSkip);

  assert( bSkip==0 );
  switch( serial_type ){
    case 1: { /* 1-byte signed integer */
      lhs = ONE_BYTE_INT(aKey);
      break;
    }
    case 2: { /* 2-byte signed integer */
      lhs = TWO_BYTE_INT(aKey);
      break;
    }
    case 3: { /* 3-byte signed integer */
      lhs = THREE_BYTE_INT(aKey);
      break;
    }
    case 4: { /* 4-byte signed integer */
      y = FOUR_BYTE_UINT(aKey);
      lhs = (i64)*(int*)&y;
      break;
    }
    case 5: { /* 6-byte signed integer */


      lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
      break;
    }
    case 6: { /* 8-byte signed integer */
      x = FOUR_BYTE_UINT(aKey);

      x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
      lhs = *(i64*)&x;
      break;
    }
    case 8: 
      lhs = 0;
      break;
    case 9:
      lhs = 1;