mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-09 14:21:03 +03:00
Make sure that UTF16 to UTF8 conversions to not read past the end of the
UTF16 input buffer if the last two bytes of the UTF16 happen to be the first half of a surrogate pair. Ticket [3fe897352e] FossilOrigin-Name: 19064d7cea838e1a93fe63743ed247f440679e97
This commit is contained in:
21
src/utf.c
21
src/utf.c
@@ -107,20 +107,20 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_UTF16LE(zIn, c){ \
|
||||
#define READ_UTF16LE(zIn, zTerm, c){ \
|
||||
c = (*zIn++); \
|
||||
c += ((*zIn++)<<8); \
|
||||
if( c>=0xD800 && c<0xE000 ){ \
|
||||
if( c>=0xD800 && c<0xE000 && zIn<zTerm ){ \
|
||||
int c2 = (*zIn++); \
|
||||
c2 += ((*zIn++)<<8); \
|
||||
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_UTF16BE(zIn, c){ \
|
||||
#define READ_UTF16BE(zIn, zTerm, c){ \
|
||||
c = ((*zIn++)<<8); \
|
||||
c += (*zIn++); \
|
||||
if( c>=0xD800 && c<0xE000 ){ \
|
||||
if( c>=0xD800 && c<0xE000 && zIn<zTerm ){ \
|
||||
int c2 = ((*zIn++)<<8); \
|
||||
c2 += (*zIn++); \
|
||||
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
|
||||
@@ -305,13 +305,13 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
|
||||
if( pMem->enc==SQLITE_UTF16LE ){
|
||||
/* UTF-16 Little-endian -> UTF-8 */
|
||||
while( zIn<zTerm ){
|
||||
READ_UTF16LE(zIn, c);
|
||||
READ_UTF16LE(zIn, zTerm, c);
|
||||
WRITE_UTF8(z, c);
|
||||
}
|
||||
}else{
|
||||
/* UTF-16 Big-endian -> UTF-8 */
|
||||
while( zIn<zTerm ){
|
||||
READ_UTF16BE(zIn, c);
|
||||
READ_UTF16BE(zIn, zTerm, c);
|
||||
WRITE_UTF8(z, c);
|
||||
}
|
||||
}
|
||||
@@ -488,6 +488,7 @@ char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
|
||||
int sqlite3Utf16ByteLen(const void *zIn, int nChar){
|
||||
int c;
|
||||
unsigned char const *z = zIn;
|
||||
unsigned char const *zTerm = &z[nChar];
|
||||
int n = 0;
|
||||
if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
|
||||
/* Using an "if (SQLITE_UTF16NATIVE==SQLITE_UTF16BE)" construct here
|
||||
@@ -500,12 +501,12 @@ int sqlite3Utf16ByteLen(const void *zIn, int nChar){
|
||||
** penalty is paid for this "if" statement.
|
||||
*/
|
||||
while( n<nChar ){
|
||||
READ_UTF16BE(z, c);
|
||||
READ_UTF16BE(z, zTerm, c);
|
||||
n++;
|
||||
}
|
||||
}else{
|
||||
while( n<nChar ){
|
||||
READ_UTF16LE(z, c);
|
||||
READ_UTF16LE(z, zTerm, c);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@@ -547,7 +548,7 @@ void sqlite3UtfSelfTest(void){
|
||||
assert( n>0 && n<=4 );
|
||||
z[0] = 0;
|
||||
z = zBuf;
|
||||
READ_UTF16LE(z, c);
|
||||
READ_UTF16LE(z, &zBuf[n], c);
|
||||
assert( c==i );
|
||||
assert( (z-zBuf)==n );
|
||||
}
|
||||
@@ -559,7 +560,7 @@ void sqlite3UtfSelfTest(void){
|
||||
assert( n>0 && n<=4 );
|
||||
z[0] = 0;
|
||||
z = zBuf;
|
||||
READ_UTF16BE(z, c);
|
||||
READ_UTF16BE(z, &zBuf[n], c);
|
||||
assert( c==i );
|
||||
assert( (z-zBuf)==n );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user