/ Check-in [3fd6a267]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add a new OP_StackDepth opcode to help detect VDBE stack leaks early, before they cause damage. For diagnostics in ticket #2832. (CVS 4612)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3fd6a267533cedcca9b8ba3533c107d7341a06c6
User & Date: drh 2007-12-12 12:00:46
Context
2007-12-12
12:25
Fix database corrupting code generation error for UPDATE OR REPLACE. ticket #2832. Still need to add test cases and additional defensive logic to avoid future occurrences of similar problems. (CVS 4613) check-in: 18e10f81 user: drh tags: trunk
12:00
Add a new OP_StackDepth opcode to help detect VDBE stack leaks early, before they cause damage. For diagnostics in ticket #2832. (CVS 4612) check-in: 3fd6a267 user: drh tags: trunk
04:38
Fix test numbering in tkt2822.test. Ticket #2830. (CVS 4611) check-in: 8fe8e9c4 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
326
327
328
329
330
331
332

333
334
335
336
337
338
339
...
423
424
425
426
427
428
429

430
431
432
433
434
435
436
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.141 2007/11/11 18:36:34 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
    sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
    sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
    sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);

    /* The top of the update loop for when there are triggers.
    */
    addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);

    mem1 = pParse->nMem++;
    sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
    
    if( !isView ){
      /* Open a cursor and make it point to the record that is
      ** being updated.
      */
................................................................................
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entries.
    ** So make the cursor point at the old record.
    */
    if( !triggers_exist ){
      addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);

      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
    }
    sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)







|







 







>







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.142 2007/12/12 12:00:46 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
    sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
    sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
    sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);

    /* The top of the update loop for when there are triggers.
    */
    addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
    sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
    mem1 = pParse->nMem++;
    sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
    
    if( !isView ){
      /* Open a cursor and make it point to the record that is
      ** being updated.
      */
................................................................................
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entries.
    ** So make the cursor point at the old record.
    */
    if( !triggers_exist ){
      addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
      sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
    }
    sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
687
688
689
690
691
692
693






















694
695
696
697
698
699
700
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.656 2007/12/04 16:54:53 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
  if( rc==SQLITE_BUSY ){
    p->rc = rc = SQLITE_BUSY;
  }else{
    rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
  }
  goto vdbe_return;
}























/* Opcode: Integer P1 * *
**
** The 32-bit integer value P1 is pushed onto the stack.
*/
case OP_Integer: {
  pTos++;







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.657 2007/12/12 12:00:46 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
  if( rc==SQLITE_BUSY ){
    p->rc = rc = SQLITE_BUSY;
  }else{
    rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
  }
  goto vdbe_return;
}

/* Opcode:  StackDepth P1 * *
**
** If P1 is less than zero, then store the current stack depth
** in P1.  If P1 is zero or greater, verify that the current stack
** depth is equal to P1 and throw an exception if it is not.
**
** This opcode is used for internal consistency checking.
*/
case OP_StackDepth: {       /* no-push */
  if( pOp->p1<0 ){
    pOp->p1 = pTos - p->aStack + 1;
  }else if( pOp->p1!=pTos - p->aStack + 1 ){
    p->pTos = pTos;
    p->rc = SQLITE_ERROR;
    p->pc = pc;
    p->errorAction = OE_Rollback;
    sqlite3SetString(&p->zErrMsg, "internal VDBE stack overflow", (char*)0);
    goto vdbe_return;
  }
  break;
}

/* Opcode: Integer P1 * *
**
** The 32-bit integer value P1 is pushed onto the stack.
*/
case OP_Integer: {
  pTos++;