Fix crash in delete when existing row has null fields. Previous code

assumed that the row had values in all columns, sigh.  Fixes bug
http://www.sqlite.org/cvstrac/tktview?tn=2289 . (CVS 3833)

FossilOrigin-Name: 81be7290a4db7b74a533aaf95c7389eb4bde6a88
This commit is contained in:
shess 2007-04-09 20:45:40 +00:00
parent 431e853715
commit 6b6ab13353
6 changed files with 155 additions and 13 deletions

View File

@ -1273,13 +1273,14 @@ static void freeStringArray(int nString, const char **pString){
int i;
for (i=0 ; i < nString ; ++i) {
free((void *) pString[i]);
if( pString[i]!=NULL ) free((void *) pString[i]);
}
free((void *) pString);
}
/* select * from %_content where rowid = [iRow]
* The caller must delete the returned array and all strings in it.
* null fields will be NULL in the returned array.
*
* TODO: Perhaps we should return pointer/length strings here for consistency
* with other code which uses pointer/length. */
@ -1303,7 +1304,11 @@ static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
values = (const char **) malloc(v->nColumn * sizeof(const char *));
for(i=0; i<v->nColumn; ++i){
values[i] = string_dup((char*)sqlite3_column_text(s, i));
if( sqlite3_column_type(s, i)==SQLITE_NULL ){
values[i] = NULL;
}else{
values[i] = string_dup((char*)sqlite3_column_text(s, i));
}
}
/* We expect only one row. We must execute another sqlite3_step()

View File

@ -1924,13 +1924,14 @@ static void freeStringArray(int nString, const char **pString){
int i;
for (i=0 ; i < nString ; ++i) {
free((void *) pString[i]);
if( pString[i]!=NULL ) free((void *) pString[i]);
}
free((void *) pString);
}
/* select * from %_content where rowid = [iRow]
* The caller must delete the returned array and all strings in it.
* null fields will be NULL in the returned array.
*
* TODO: Perhaps we should return pointer/length strings here for consistency
* with other code which uses pointer/length. */
@ -1954,7 +1955,11 @@ static int content_select(fulltext_vtab *v, sqlite_int64 iRow,
values = (const char **) malloc(v->nColumn * sizeof(const char *));
for(i=0; i<v->nColumn; ++i){
values[i] = string_dup((char*)sqlite3_column_text(s, i));
if( sqlite3_column_type(s, i)==SQLITE_NULL ){
values[i] = NULL;
}else{
values[i] = string_dup((char*)sqlite3_column_text(s, i));
}
}
/* We expect only one row. We must execute another sqlite3_step()

View File

@ -1,5 +1,5 @@
C Fix\sstack\sbuffer\soverrun\sproblem\sin\sthe\stest\sharness.\s(CVS\s3832)
D 2007-04-09T20:30:11
C Fix\scrash\sin\sdelete\swhen\sexisting\srow\shas\snull\sfields.\s\sPrevious\scode\nassumed\sthat\sthe\srow\shad\svalues\sin\sall\scolumns,\ssigh.\s\sFixes\sbug\nhttp://www.sqlite.org/cvstrac/tktview?tn=2289\s.\s(CVS\s3833)
D 2007-04-09T20:45:41
F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -22,7 +22,7 @@ F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
F ext/fts1/ft_hash.h 1a35e654a235c2c662d3ca0dfc3138ad60b8b7d5
F ext/fts1/fts1.c 7585d9cb7ad7bcdf162936ab1fd64868f2f55ea5
F ext/fts1/fts1.c 1ee986c31a7080d509602fa182738c5a8862fbff
F ext/fts1/fts1.h 6060b8f62c1d925ea8356cb1a6598073eb9159a6
F ext/fts1/fts1_hash.c 3196cee866edbebb1c0521e21672e6d599965114
F ext/fts1/fts1_hash.h 957d378355ed29f672cd5add012ce8b088a5e089
@ -34,7 +34,7 @@ F ext/fts1/fulltext.h 08525a47852d1d62a0be81d3fc3fe2d23b094efd
F ext/fts1/simple_tokenizer.c 1844d72f7194c3fd3d7e4173053911bf0661b70d
F ext/fts1/tokenizer.h 0c53421b832366d20d720d21ea3e1f6e66a36ef9
F ext/fts2/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts2/fts2.c 8d69d6e4b48b0de4350e10c9c76649c638e35997
F ext/fts2/fts2.c acfce1c936d50615f21b63b71f6e86730da64a8c
F ext/fts2/fts2.h bbdab26d34f91974d5b9ade8b7836c140a7c4ce1
F ext/fts2/fts2_hash.c b3f22116d4ef0bc8f2da6e3fdc435c86d0951a9b
F ext/fts2/fts2_hash.h e283308156018329f042816eb09334df714e105e
@ -219,6 +219,7 @@ F test/fts1f.test 2d6cb10d8b7a4e6edc321bbdb3982f1f48774714
F test/fts1i.test 6bfe08cdfdced063a39a50c8601da65e6274d879
F test/fts1j.test e4c0ffcd0ba2adce09c6b7b43ffd0749b5fda5c7
F test/fts1k.test fdf295cb797ba6a2ef81ec41cb98df0ceb2e572c
F test/fts1l.test 15c119ed2362b2b28d5300c0540a6a43eab66c36
F test/fts1porter.test d86e9c3e0c7f8ff95add6582b4b585fb4e02b96d
F test/fts2a.test 103fc178d134c54c44c1938a4331e9e2030792d9
F test/fts2b.test 964abc0236c849c07ca1ae496bb25c268ae94816
@ -232,6 +233,7 @@ F test/fts2i.test 1b22451d1f13f7c509baec620dc3a4a754885dd6
F test/fts2j.test f68d7611f76309bc8b94170f3740d9fbbc061d9b
F test/fts2k.test 222d0b3bc8667753f18406aaea9906a6098ea016
F test/fts2l.test 4c53c89ce3919003765ff4fd8d98ecf724d97dd3
F test/fts2m.test 4b30142ead6f3ed076e880a2a464064c5ad58c51
F test/func.test 019d706b2458dfdf239c74cc31143446de1ee44a
F test/hook.test 7e7645fd9a033f79cce8fdff151e32715e7ec50a
F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
@ -455,7 +457,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P ba5f4a55fad183a1698555b256f43f63451f5fc6
R 5ef4b02d2117db2ca987c4c827be07e2
U drh
Z aefa6d34865394c1dd78203eae52ac99
P cad9faf3ad99b68be4618dff4b3497b15b9e6d9d
R 66cd54d39dd95145a99973d21d5eff33
U shess
Z 50d829f2eb908722f9e9fda676f48500

View File

@ -1 +1 @@
cad9faf3ad99b68be4618dff4b3497b15b9e6d9d
81be7290a4db7b74a533aaf95c7389eb4bde6a88

65
test/fts1l.test Normal file
View File

@ -0,0 +1,65 @@
# 2007 April 9
#
# The author disclaims copyright to this source code.
#
#*************************************************************************
# This file implements regression tests for SQLite library. fts1
# DELETE handling assumed all fields were non-null. This was not
# the intention at all.
#
# $Id: fts1l.test,v 1.1 2007/04/09 20:45:42 shess Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If SQLITE_ENABLE_FTS1 is defined, omit this file.
ifcapable !fts1 {
finish_test
return
}
db eval {
CREATE VIRTUAL TABLE t1 USING fts1(col_a, col_b);
INSERT INTO t1(rowid, col_a, col_b) VALUES(1, 'testing', 'testing');
INSERT INTO t1(rowid, col_a, col_b) VALUES(2, 'only a', null);
INSERT INTO t1(rowid, col_a, col_b) VALUES(3, null, 'only b');
INSERT INTO t1(rowid, col_a, col_b) VALUES(4, null, null);
}
do_test fts1m-1.0 {
execsql {
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {2 2 4}
do_test fts1m-1.1 {
execsql {
DELETE FROM t1 WHERE rowid = 1;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {1 1 3}
do_test fts1m-1.2 {
execsql {
DELETE FROM t1 WHERE rowid = 2;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {0 1 2}
do_test fts1m-1.3 {
execsql {
DELETE FROM t1 WHERE rowid = 3;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {0 0 1}
do_test fts1m-1.4 {
execsql {
DELETE FROM t1 WHERE rowid = 4;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {0 0 0}
finish_test

65
test/fts2m.test Normal file
View File

@ -0,0 +1,65 @@
# 2007 April 9
#
# The author disclaims copyright to this source code.
#
#*************************************************************************
# This file implements regression tests for SQLite library. fts2
# DELETE handling assumed all fields were non-null. This was not
# the intention at all.
#
# $Id: fts2m.test,v 1.1 2007/04/09 20:45:42 shess Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If SQLITE_ENABLE_FTS2 is defined, omit this file.
ifcapable !fts2 {
finish_test
return
}
db eval {
CREATE VIRTUAL TABLE t1 USING fts2(col_a, col_b);
INSERT INTO t1(rowid, col_a, col_b) VALUES(1, 'testing', 'testing');
INSERT INTO t1(rowid, col_a, col_b) VALUES(2, 'only a', null);
INSERT INTO t1(rowid, col_a, col_b) VALUES(3, null, 'only b');
INSERT INTO t1(rowid, col_a, col_b) VALUES(4, null, null);
}
do_test fts2m-1.0 {
execsql {
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {2 2 4}
do_test fts2m-1.1 {
execsql {
DELETE FROM t1 WHERE rowid = 1;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {1 1 3}
do_test fts2m-1.2 {
execsql {
DELETE FROM t1 WHERE rowid = 2;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {0 1 2}
do_test fts2m-1.3 {
execsql {
DELETE FROM t1 WHERE rowid = 3;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {0 0 1}
do_test fts2m-1.4 {
execsql {
DELETE FROM t1 WHERE rowid = 4;
SELECT COUNT(col_a), COUNT(col_b), COUNT(*) FROM t1;
}
} {0 0 0}
finish_test