Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
81be7290a4db7b74a533aaf95c7389eb |
User & Date: | shess 2007-04-09 20:45:41.000 |
Context
2007-04-10
| ||
13:51 | Be careful not to use the result of sqlite3_value_blob() after changing the representation of an object. Ticket #2290. (CVS 3834) (check-in: e14374e4e6 user: drh tags: trunk) | |
2007-04-09
| ||
20:45 | 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) (check-in: 81be7290a4 user: shess tags: trunk) | |
20:30 | Fix stack buffer overrun problem in the test harness. (CVS 3832) (check-in: cad9faf3ad user: drh tags: trunk) | |
Changes
Changes to ext/fts1/fts1.c.
︙ | ︙ | |||
1269 1270 1271 1272 1273 1274 1275 | return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s); } static void freeStringArray(int nString, const char **pString){ int i; for (i=0 ; i < nString ; ++i) { | | > | 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 | return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s); } static void freeStringArray(int nString, const char **pString){ int i; for (i=0 ; i < nString ; ++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. */ static int content_select(fulltext_vtab *v, sqlite_int64 iRow, const char ***pValues){ sqlite3_stmt *s; const char **values; |
︙ | ︙ | |||
1299 1300 1301 1302 1303 1304 1305 | if( rc!=SQLITE_OK ) return rc; rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s); if( rc!=SQLITE_ROW ) return rc; values = (const char **) malloc(v->nColumn * sizeof(const char *)); for(i=0; i<v->nColumn; ++i){ | > > > | > | 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | if( rc!=SQLITE_OK ) return rc; rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s); if( rc!=SQLITE_ROW ) return rc; values = (const char **) malloc(v->nColumn * sizeof(const char *)); for(i=0; i<v->nColumn; ++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() * to complete the iteration; otherwise the table will remain locked. */ rc = sqlite3_step(s); if( rc==SQLITE_DONE ){ *pValues = values; |
︙ | ︙ |
Changes to ext/fts2/fts2.c.
︙ | ︙ | |||
1920 1921 1922 1923 1924 1925 1926 | return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s); } static void freeStringArray(int nString, const char **pString){ int i; for (i=0 ; i < nString ; ++i) { | | > | 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 | return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s); } static void freeStringArray(int nString, const char **pString){ int i; for (i=0 ; i < nString ; ++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. */ static int content_select(fulltext_vtab *v, sqlite_int64 iRow, const char ***pValues){ sqlite3_stmt *s; const char **values; |
︙ | ︙ | |||
1950 1951 1952 1953 1954 1955 1956 | if( rc!=SQLITE_OK ) return rc; rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s); if( rc!=SQLITE_ROW ) return rc; values = (const char **) malloc(v->nColumn * sizeof(const char *)); for(i=0; i<v->nColumn; ++i){ | > > > | > | 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 | if( rc!=SQLITE_OK ) return rc; rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s); if( rc!=SQLITE_ROW ) return rc; values = (const char **) malloc(v->nColumn * sizeof(const char *)); for(i=0; i<v->nColumn; ++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() * to complete the iteration; otherwise the table will remain locked. */ rc = sqlite3_step(s); if( rc==SQLITE_DONE ){ *pValues = values; |
︙ | ︙ |
Added test/fts1l.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 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 |
Added test/fts2m.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 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 |