Make sure strings returned by sqlite3_value_text() and sqlite3_value_text16()

are always '\000'-terminated. (CVS 3391)

FossilOrigin-Name: 2c63588b45f4e1ab9b9f1b72c901f3800433424a
This commit is contained in:
drh 2006-09-04 15:53:53 +00:00
parent f80ad49f72
commit f0313813ec
5 changed files with 101 additions and 32 deletions

View File

@ -1,5 +1,5 @@
C Fix\sbugs\sin\stest\sscripts\sso\sthat\sfulltest\swill\spass.\s(CVS\s3390)
D 2006-09-02T22:14:59
C Make\ssure\sstrings\sreturned\sby\ssqlite3_value_text()\sand\ssqlite3_value_text16()\nare\salways\s'\\000'-terminated.\s(CVS\s3391)
D 2006-09-04T15:53:53
F Makefile.in cabd42d34340f49260bc2a7668c38eba8d4cfd99
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -91,7 +91,7 @@ F src/sqlite3ext.h 11a046b3519c4b9b7709e6d6a95c3a36366f684a
F src/sqliteInt.h 259adce944cc3b28da1fa3df9beb9ba86017a45d
F src/table.c d8817f43a6c6bf139487db161760b9e1e02da3f1
F src/tclsqlite.c e029f739bed90071789fe81a226d53e97a80a4d8
F src/test1.c cb3688f5d2094dc708a7959bd99aed411e096e49
F src/test1.c c8c3b2fd9e71cda3e6598f84357734cfd4fb93e2
F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
F src/test3.c 85135c09560c48bdb0a23c9b890ab405486b8ec9
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
@ -118,7 +118,7 @@ F src/vdbeInt.h e3eaab262b67b84474625cfc38aec1125c32834b
F src/vdbeapi.c 81f531d7dc5c898131b02ef85f6c6144ab2892cf
F src/vdbeaux.c 9fab61427a0741c9c123e8ff16e349b1f90397be
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
F src/vdbemem.c 26623176bf1c616aa478da958fac49502491a921
F src/vtab.c 7fc0624c2bb6156c3d99e2ce706f2a5b54094e36
F src/where.c 75a89957fcb8c068bec55caa4e9d2ed5fa0b0724
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
@ -234,6 +234,7 @@ F test/misc2.test 9740c2fb7e4a69b2bebd4c5fd9ba45ae27b27e98
F test/misc3.test 7bd937e2c62bcc6be71939faf068d506467b1e03
F test/misc4.test b043a05dea037cca5989f3ae09552fa16119bc80
F test/misc5.test 83bceca3d38ed10ced00271e02b26b24795def83
F test/misc6.test 6d1b1535ad9e8788334ac2462deec662a2f82c57
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
F test/null.test 9503e1f63e959544c006d9f01709c5b5eab67d54
@ -395,7 +396,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 7279ddd08444d54712f738d997c5d11f6af064c1
R 0154a554f51203117c37cdba6d80f9d4
P 367bd8376f323beb3148eab86ada1a3cb379ba3b
R 65d3fac7dc50afc9b2c593fb5d16df61
U drh
Z 1d0c9fd6f6dadab65fcbce0df688ab5a
Z 7a672874943fae922a528231fba04d93

View File

@ -1 +1 @@
367bd8376f323beb3148eab86ada1a3cb379ba3b
2c63588b45f4e1ab9b9f1b72c901f3800433424a

View File

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.218 2006/09/02 14:50:24 drh Exp $
** $Id: test1.c,v 1.219 2006/09/04 15:53:53 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -442,6 +442,34 @@ static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
}
}
/*
** These are test functions. hex8() interprets its argument as
** UTF8 and returns a hex encoding. hex16le() interprets its argument
** as UTF16le and returns a hex encoding.
*/
static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
const unsigned char *z;
int i;
char zBuf[200];
z = sqlite3_value_text(argv[0]);
for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
sprintf(&zBuf[i*2], "%02x", z[i]&0xff);
}
zBuf[i*2] = 0;
sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
}
static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
const unsigned short int *z;
int i;
char zBuf[400];
z = sqlite3_value_text16(argv[0]);
for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
sprintf(&zBuf[i*4], "%04x", z[i]&0xff);
}
zBuf[i*4] = 0;
sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
}
/*
** A structure into which to accumulate text.
*/
@ -548,6 +576,10 @@ static int test_create_function(
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
ifnullFunc, 0, 0);
rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
hex8Func, 0, 0);
rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
hex16Func, 0, 0);
#ifndef SQLITE_OMIT_UTF16
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also
@ -1417,6 +1449,7 @@ static int test_changes(
** the FLAG option of sqlite3_bind is "static"
*/
static char *sqlite_static_bind_value = 0;
static int sqlite_static_bind_nbyte = 0;
/*
** Usage: sqlite3_bind VM IDX VALUE FLAGS
@ -1449,6 +1482,9 @@ static int test_bind(
rc = sqlite3_bind_null(pStmt, idx);
}else if( strcmp(argv[4],"static")==0 ){
rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
}else if( strcmp(argv[4],"static-nbytes")==0 ){
rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
sqlite_static_bind_nbyte, 0);
}else if( strcmp(argv[4],"normal")==0 ){
rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
}else if( strcmp(argv[4],"blob10")==0 ){
@ -3968,6 +4004,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#endif
Tcl_LinkVar(interp, "sqlite_static_bind_value",
(char*)&sqlite_static_bind_value, TCL_LINK_STRING);
Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
(char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_temp_directory",
(char*)&sqlite3_temp_directory, TCL_LINK_STRING);
Tcl_LinkVar(interp, "bitmask_size",

View File

@ -50,14 +50,6 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
if( rc==SQLITE_NOMEM ){
/*
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Null;
pMem->z = 0;
*/
}
return rc;
#endif
}
@ -127,22 +119,9 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
** Make sure the given Mem is \u0000 terminated.
*/
int sqlite3VdbeMemNulTerminate(Mem *pMem){
/* In SQLite, a string without a nul terminator occurs when a string
** is loaded from disk (in this case the memory management is ephemeral),
** or when it is supplied by the user as a bound variable or function
** return value. Therefore, the memory management of the string must be
** either ephemeral, static or controlled by a user-supplied destructor.
*/
assert(
!(pMem->flags&MEM_Str) || /* it's not a string, or */
(pMem->flags&MEM_Term) || /* it's nul term. already, or */
(pMem->flags&(MEM_Ephem|MEM_Static)) || /* it's static or ephem, or */
(pMem->flags&MEM_Dyn && pMem->xDel) /* external management */
);
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
return SQLITE_OK; /* Nothing to do */
}
if( pMem->flags & (MEM_Static|MEM_Ephem) ){
return sqlite3VdbeMemMakeWriteable(pMem);
}else{
@ -151,7 +130,11 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
memcpy(z, pMem->z, pMem->n);
z[pMem->n] = 0;
z[pMem->n+1] = 0;
pMem->xDel(pMem->z);
if( pMem->xDel ){
pMem->xDel(pMem->z);
}else{
sqliteFree(pMem->z);
}
pMem->xDel = 0;
pMem->z = z;
}
@ -782,7 +765,9 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
return 0;
}
}
}else if( !(pVal->flags&MEM_Blob) ){
sqlite3VdbeMemNulTerminate(pVal);
}else{
assert( (pVal->flags&MEM_Blob)==0 );
sqlite3VdbeMemStringify(pVal, enc);
assert( 0==(1&(int)pVal->z) );
}

45
test/misc6.test Normal file
View File

@ -0,0 +1,45 @@
# 2006 September 4
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure sqlite3_value_text()
# always returns a null-terminated string.
#
# $Id: misc6.test,v 1.1 2006/09/04 15:53:53 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test misc6-1.1 {
set DB [sqlite3_connection_pointer db]
sqlite3_create_function $DB
set STMT [sqlite3_prepare $DB {SELECT hex8(?)} -1 DUMMY]
set sqlite_static_bind_value {0123456789}
set sqlite_static_bind_nbyte 5
sqlite_bind $STMT 1 {} static-nbytes
sqlite3_step $STMT
} SQLITE_ROW
do_test misc6-1.2 {
sqlite3_column_text $STMT 0
} {3031323334}
do_test misc6-1.3 {
sqlite3_finalize $STMT
set STMT [sqlite3_prepare $DB {SELECT hex16(?)} -1 DUMMY]
set sqlite_static_bind_value {0123456789}
set sqlite_static_bind_nbyte 5
sqlite_bind $STMT 1 {} static-nbytes
sqlite3_step $STMT
} SQLITE_ROW
do_test misc6-1.4 {
sqlite3_column_text $STMT 0
} {00300031003200330034}
finish_test