diff options
author | drh <drh@noemail.net> | 2001-09-15 13:15:12 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2001-09-15 13:15:12 +0000 |
commit | 092d0350d5bcfe2d1a02dc3a821b474c9c0ecdbd (patch) | |
tree | f1438bc5ce605f19e22fb7240a04cbba9b4c20b1 /src | |
parent | b3e05a662ad09159dad26a4520e815ae6550b1b7 (diff) | |
download | sqlite-092d0350d5bcfe2d1a02dc3a821b474c9c0ecdbd.tar.gz sqlite-092d0350d5bcfe2d1a02dc3a821b474c9c0ecdbd.zip |
Limit the total data in a single row to 2^16-1 bytes. (CVS 248)
FossilOrigin-Name: 8fdec4d8b6043471f21235bc8918c9a8d838f508
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 11 | ||||
-rw-r--r-- | src/pager.h | 8 | ||||
-rw-r--r-- | src/sqlite.h.in | 3 | ||||
-rw-r--r-- | src/sqliteInt.h | 9 | ||||
-rw-r--r-- | src/util.c | 3 | ||||
-rw-r--r-- | src/vdbe.c | 98 |
6 files changed, 83 insertions, 49 deletions
diff --git a/src/btree.c b/src/btree.c index 3baa48733..2dc2d4c67 100644 --- a/src/btree.c +++ b/src/btree.c @@ -21,7 +21,7 @@ ** http://www.hwaci.com/drh/ ** ************************************************************************* -** $Id: btree.c,v 1.27 2001/09/14 18:54:08 drh Exp $ +** $Id: btree.c,v 1.28 2001/09/15 13:15:13 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -73,9 +73,12 @@ ** Change these typedefs when porting to new architectures. */ typedef unsigned int uptr; -/* typedef unsigned int u32; -- already defined in sqliteInt.h */ -typedef unsigned short int u16; -typedef unsigned char u8; + +/* There are already definedin sqliteInt.h... +** typedef unsigned int u32; +** typedef unsigned short int u16; +** typedef unsigned char u8; +*/ /* ** This macro casts a pointer to an integer. Useful for doing diff --git a/src/pager.h b/src/pager.h index 8ae8b9ee6..363704658 100644 --- a/src/pager.h +++ b/src/pager.h @@ -25,7 +25,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.9 2001/09/14 18:54:09 drh Exp $ +** @(#) $Id: pager.h,v 1.10 2001/09/15 13:15:13 drh Exp $ */ /* @@ -34,6 +34,12 @@ #define SQLITE_PAGE_SIZE 1024 /* +** Maximum number of pages in one database. (This is a limitation of +** imposed by 4GB files size limits.) +*/ +#define SQLITE_MAX_PAGE 1073741823 + +/* ** The type used to represent a page number. The first page in a file ** is called page 1. 0 is used to represent "not a page". */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 60aa491bf..c22b9cb3c 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -24,7 +24,7 @@ ** This header file defines the interface that the sqlite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.15 2001/09/15 00:57:29 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.16 2001/09/15 13:15:13 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -161,6 +161,7 @@ int sqlite_exec( #define SQLITE_PROTOCOL 14 /* Database lock protocol error */ #define SQLITE_EMPTY 15 /* Database table is empty */ #define SQLITE_SCHEMA 16 /* The database schema changed */ +#define SQLITE_TOOBIG 17 /* Too much data for one row of a table */ /* This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 134653bc7..8ea3e3949 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -23,7 +23,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.48 2001/09/15 00:57:29 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.49 2001/09/15 13:15:13 drh Exp $ */ #include "sqlite.h" #include "vdbe.h" @@ -42,9 +42,12 @@ #define TEMP_PAGES 25 /* -** The paging system deals with 32-bit integers. +** Integers of known sizes. These typedefs much change for architectures +** where the sizes very. */ -typedef unsigned int u32; +typedef unsigned int u32; /* 4-byte unsigned integer */ +typedef unsigned short int u16; /* 2-byte unsigned integer */ +typedef unsigned char u8; /* 1-byte unsigned integer */ /* ** If memory allocation problems are found, recompile with diff --git a/src/util.c b/src/util.c index b894f2300..58103ba8d 100644 --- a/src/util.c +++ b/src/util.c @@ -26,7 +26,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.23 2001/09/15 00:57:29 drh Exp $ +** $Id: util.c,v 1.24 2001/09/15 13:15:13 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -997,6 +997,7 @@ const char *sqliteErrStr(int rc){ case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; + case SQLITE_TOOBIG: z = "too much data for one table row"; break; default: z = "unknown error"; break; } return z; diff --git a/src/vdbe.c b/src/vdbe.c index e25dca464..6414dc538 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -41,7 +41,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.67 2001/09/15 00:57:29 drh Exp $ +** $Id: vdbe.c,v 1.68 2001/09/15 13:15:13 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -456,7 +456,7 @@ int sqliteVdbeMakeLabel(Vdbe *p){ i = p->nLabel++; if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; - p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(int)); + p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel==0 ){ p->nLabel = 0; @@ -1774,22 +1774,24 @@ case OP_NotNull: { ** Convert the top P1 entries of the stack into a single entry ** suitable for use as a data record in a database table. To do this ** all entries (except NULLs) are converted to strings and -** concatenated. The null-terminators are preserved by the concatation -** and serve as a boundry marker between columns. The lowest entry +** concatenated. The null-terminators are included on all string +** except for NULL columns which are represented by zero bytes. +** The lowest entry ** on the stack is the first in the concatenation and the top of ** the stack is the last. After all columns are concatenated, an -** index header is added. The index header consists of P1 integers +** index header is added. The index header consists of P1 16-bit integers ** which hold the offset of the beginning of each column data from the -** beginning of the completed record including the header. Header -** entries for NULL fields point to where the first byte of the column -** would have been stored if the column had held any bytes. +** beginning of the completed record including the header. +** +** The OP_Column opcode is used to unpack a record manufactured with +** the opcode. */ case OP_MakeRecord: { char *zNewRecord; int nByte; int nField; int i, j; - int addr; + u16 addr; nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) @@ -1800,14 +1802,18 @@ case OP_MakeRecord: { nByte += aStack[i].n; } } - nByte += sizeof(int)*nField; + nByte += sizeof(addr)*nField; + if( nByte>65535 ){ + rc = SQLITE_TOOBIG; + goto abort_due_to_error; + } zNewRecord = sqliteMalloc( nByte ); if( zNewRecord==0 ) goto no_mem; j = 0; - addr = sizeof(int)*nField; + addr = sizeof(addr)*nField; for(i=p->tos-nField+1; i<=p->tos; i++){ - memcpy(&zNewRecord[j], (char*)&addr, sizeof(int)); - j += sizeof(int); + memcpy(&zNewRecord[j], (char*)&addr, sizeof(addr)); + j += sizeof(addr); if( (aStack[i].flags & STK_Null)==0 ){ addr += aStack[i].n; } @@ -1906,7 +1912,7 @@ case OP_MakeIdxKey: { nField = pOp->p1; VERIFY( if( p->tos+1<nField ) goto not_enough_stack; ) - nByte = sizeof(int); + nByte = sizeof(u32); for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ nByte++; @@ -1927,7 +1933,7 @@ case OP_MakeIdxKey: { } zNewKey[j++] = 0; Integerify(p, p->tos-nField); - memcpy(&zNewKey[j], &aStack[p->tos-nField].i, sizeof(int)); + memcpy(&zNewKey[j], &aStack[p->tos-nField].i, sizeof(u32)); PopStack(p, nField+1); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; @@ -2369,15 +2375,12 @@ case OP_KeyAsData: { /* Opcode: Column P1 P2 * ** -** Interpret the data in the most recent fetch from cursor P1 -** is a structure built using the MakeRecord instruction. -** Push onto the stack the value of the P2-th field of that -** structure. -** -** The value pushed is a pointer to the data stored in the cursor. -** The value will go away the next time the cursor is modified in -** any way. Make a copy of the string (using -** "Concat 1 0 0") if it needs to persist longer than that. +** Interpret the data that cursor P1 points to as +** a structure built using the MakeRecord instruction. +** (See the MakeRecord opcode for additional information about +** the format of the data.) +** Push onto the stack the value of the P2-th column contained +** in the data. ** ** If the KeyAsData opcode has previously executed on this cursor, ** then the field might be extracted from the key rather than the @@ -2385,7 +2388,7 @@ case OP_KeyAsData: { */ case OP_Column: { int amt, offset, nCol, payloadSize; - int aHdr[10]; + u16 aHdr[10]; static const int mxHdr = sizeof(aHdr)/sizeof(aHdr[0]); int i = pOp->p1; int p2 = pOp->p2; @@ -2417,14 +2420,14 @@ case OP_Column: { ** three times. */ (*xSize)(pCrsr, &payloadSize); - if( payloadSize < sizeof(int)*(p2+1) ){ + if( payloadSize < sizeof(aHdr[0])*(p2+1) ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( p2+1<mxHdr ){ (*xRead)(pCrsr, 0, sizeof(aHdr[0])*(p2+2), (char*)aHdr); nCol = aHdr[0]; - nCol /= sizeof(int); + nCol /= sizeof(aHdr[0]); offset = aHdr[p2]; if( p2 == nCol-1 ){ amt = payloadSize - offset; @@ -2432,13 +2435,14 @@ case OP_Column: { amt = aHdr[p2+1] - offset; } }else{ - sqliteBtreeData(pCrsr, 0, sizeof(int), (char*)&nCol); - nCol /= sizeof(int); + sqliteBtreeData(pCrsr, 0, sizeof(aHdr[0]), (char*)aHdr); + nCol = aHdr[0]/sizeof(aHdr[0]); if( p2 == nCol-1 ){ - (*xRead)(pCrsr, sizeof(int)*p2, sizeof(int), (char*)&offset); + (*xRead)(pCrsr, sizeof(aHdr[0])*p2, sizeof(aHdr[0]), (char*)aHdr); + offset = aHdr[0]; amt = payloadSize - offset; }else{ - (*xRead)(pCrsr, sizeof(int)*p2, sizeof(int)*2, (char*)aHdr); + (*xRead)(pCrsr, sizeof(aHdr[0])*p2, sizeof(aHdr[0])*2, (char*)aHdr); offset = aHdr[0]; amt = aHdr[1] - offset; } @@ -2447,6 +2451,10 @@ case OP_Column: { rc = SQLITE_CORRUPT; goto abort_due_to_error; } + + /* amt and offset now hold the offset to the start of data and the + ** amount of data. Go get the data and put it on the stack. + */ if( amt==0 ){ aStack[tos].flags = STK_Null; }else{ @@ -2480,7 +2488,7 @@ case OP_Recno: { if( p->aCsr[i].recnoIsValid ){ v = p->aCsr[i].lastRecno; }else{ - sqliteBtreeKey(pCrsr, 0, sizeof(int), (char*)&v); + sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v); } aStack[tos].i = v; aStack[tos].flags = STK_Int; @@ -2626,7 +2634,7 @@ case OP_NextIdx: { if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); - if( res>0 || size!=pCrsr->nKey+sizeof(int) || + if( res>0 || size!=pCrsr->nKey+sizeof(u32) || sqliteBtreeKey(pCur, 0, pCrsr->nKey, pCrsr->zBuf)!=pCrsr->nKey || strncmp(pCrsr->zKey, pCrsr->zBuf, pCrsr->nKey)!=0 ){ @@ -2634,7 +2642,7 @@ case OP_NextIdx: { POPSTACK; }else{ int recno; - sqliteBtreeKey(pCur, pCrsr->nKey, sizeof(int), (char*)&recno); + sqliteBtreeKey(pCur, pCrsr->nKey, sizeof(u32), (char*)&recno); p->aCsr[i].lastRecno = aStack[tos].i = recno; p->aCsr[i].recnoIsValid = 1; aStack[tos].flags = STK_Int; @@ -2812,7 +2820,7 @@ case OP_ListWrite: { VERIFY( if( p->tos<0 ) goto not_enough_stack; ) pKeylist = p->apList[i]; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ - pKeylist = sqliteMalloc( sizeof(Keylist)+999*sizeof(int) ); + pKeylist = sqliteMalloc( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); if( pKeylist==0 ) goto no_mem; pKeylist->nKey = 1000; pKeylist->nRead = 0; @@ -3774,11 +3782,23 @@ default: { }else if( aStack[i].flags & STK_Real ){ fprintf(p->trace, " r:%g", aStack[i].r); }else if( aStack[i].flags & STK_Str ){ - if( aStack[i].flags & STK_Dyn ){ - fprintf(p->trace, " z:[%.11s]", zStack[i]); - }else{ - fprintf(p->trace, " s:[%.11s]", zStack[i]); + int j, k; + char zBuf[100]; + zBuf[0] = ' '; + zBuf[1] = (aStack[i].flags & STK_Dyn)!=0 ? 'z' : 's'; + zBuf[2] = ':'; + k = 3; + for(j=0; j<15 && j<aStack[i].n; j++){ + int c = zStack[i][j]; + if( c==0 && j==aStack[i].n-1 ) break; + if( isprint(c) && !isspace(c) ){ + zBuf[k++] = c; + }else{ + zBuf[k++] = '.'; + } } + zBuf[k++] = 0; + fprintf(p->trace, "%s", zBuf); }else{ fprintf(p->trace, " ???"); } |