aboutsummaryrefslogtreecommitdiff
path: root/src/test_func.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2009-10-23 18:15:46 +0000
committerdrh <drh@noemail.net>2009-10-23 18:15:46 +0000
commit7c95b0f3dab6f6924826f32ee570e852dc4fc946 (patch)
tree2802c661095c1457df412dcd70b2e6062e534d00 /src/test_func.c
parent9bd1b449442b3e8faeb2da6607cf5a52edc5e96c (diff)
downloadsqlite-7c95b0f3dab6f6924826f32ee570e852dc4fc946.tar.gz
sqlite-7c95b0f3dab6f6924826f32ee570e852dc4fc946.zip
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
Diffstat (limited to 'src/test_func.c')
-rw-r--r--src/test_func.c107
1 files changed, 105 insertions, 2 deletions
diff --git a/src/test_func.c b/src/test_func.c
index d0f47d400..355767461 100644
--- a/src/test_func.c
+++ b/src/test_func.c
@@ -313,6 +313,108 @@ static void test_eval(
}
+/*
+** convert one character from hex to binary
+*/
+static int testHexChar(char c){
+ if( c>='0' && c<='9' ){
+ return c - '0';
+ }else if( c>='a' && c<='f' ){
+ return c - 'a' + 10;
+ }else if( c>='A' && c<='F' ){
+ return c - 'A' + 10;
+ }
+ return 0;
+}
+
+/*
+** Convert hex to binary.
+*/
+static void testHexToBin(const char *zIn, char *zOut){
+ while( zIn[0] && zIn[1] ){
+ *(zOut++) = (testHexChar(zIn[0])<<4) + testHexChar(zIn[1]);
+ zIn += 2;
+ }
+}
+
+/*
+** hex_to_utf16be(HEX)
+**
+** Convert the input string from HEX into binary. Then return the
+** result using sqlite3_result_text16le().
+*/
+static void testHexToUtf16be(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **argv
+){
+ int n;
+ const char *zIn;
+ char *zOut;
+ assert( nArg==1 );
+ n = sqlite3_value_bytes(argv[0]);
+ zIn = (const char*)sqlite3_value_text(argv[0]);
+ zOut = sqlite3_malloc( n/2 );
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ }else{
+ testHexToBin(zIn, zOut);
+ sqlite3_result_text16be(pCtx, zOut, n/2, sqlite3_free);
+ }
+}
+
+/*
+** hex_to_utf8(HEX)
+**
+** Convert the input string from HEX into binary. Then return the
+** result using sqlite3_result_text16le().
+*/
+static void testHexToUtf8(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **argv
+){
+ int n;
+ const char *zIn;
+ char *zOut;
+ assert( nArg==1 );
+ n = sqlite3_value_bytes(argv[0]);
+ zIn = (const char*)sqlite3_value_text(argv[0]);
+ zOut = sqlite3_malloc( n/2 );
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ }else{
+ testHexToBin(zIn, zOut);
+ sqlite3_result_text(pCtx, zOut, n/2, sqlite3_free);
+ }
+}
+
+/*
+** hex_to_utf16le(HEX)
+**
+** Convert the input string from HEX into binary. Then return the
+** result using sqlite3_result_text16le().
+*/
+static void testHexToUtf16le(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **argv
+){
+ int n;
+ const char *zIn;
+ char *zOut;
+ assert( nArg==1 );
+ n = sqlite3_value_bytes(argv[0]);
+ zIn = (const char*)sqlite3_value_text(argv[0]);
+ zOut = sqlite3_malloc( n/2 );
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ }else{
+ testHexToBin(zIn, zOut);
+ sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free);
+ }
+}
+
static int registerTestFunctions(sqlite3 *db){
static const struct {
char *zName;
@@ -324,7 +426,10 @@ static int registerTestFunctions(sqlite3 *db){
{ "test_destructor", 1, SQLITE_UTF8, test_destructor},
#ifndef SQLITE_OMIT_UTF16
{ "test_destructor16", 1, SQLITE_UTF8, test_destructor16},
+ { "hex_to_utf16be", 1, SQLITE_UTF8, testHexToUtf16be},
+ { "hex_to_utf16le", 1, SQLITE_UTF8, testHexToUtf16le},
#endif
+ { "hex_to_utf8", 1, SQLITE_UTF8, testHexToUtf8},
{ "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count},
{ "test_auxdata", -1, SQLITE_UTF8, test_auxdata},
{ "test_error", 1, SQLITE_UTF8, test_error},
@@ -447,8 +552,6 @@ abuse_err:
return TCL_ERROR;
}
-
-
/*
** Register commands with the TCL interpreter.
*/