Fix for sqlite3_blob_write(): If either 3rd or 4th argument is less than zero, return SQLITE_ERROR. H17879. (CVS 5762)

FossilOrigin-Name: f6074c0b9b5ba51d131509dba2aec80d0fcf3b7e
diff --git a/src/test1.c b/src/test1.c
index 722c09e..c54173e 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -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.325 2008/09/11 10:29:16 danielk1977 Exp $
+** $Id: test1.c,v 1.326 2008/10/02 14:49:02 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -1559,7 +1559,7 @@
 }
 
 /*
-** sqlite3_blob_write CHANNEL OFFSET DATA
+** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA?
 **
 **   This command is used to test the sqlite3_blob_write() in ways that
 **   the Tcl channel interface does not. The first argument should
@@ -1588,16 +1588,13 @@
   unsigned char *zBuf;
   int nBuf;
   
-  if( objc!=4 ){
-    Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA");
+  if( objc!=4 && objc!=5 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?");
     return TCL_ERROR;
   }
 
   channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), &notUsed);
-  if( !channel
-   || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
-   || iOffset<0
-  ){ 
+  if( !channel || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){ 
     return TCL_ERROR;
   }
 
@@ -1605,6 +1602,9 @@
   pBlob = *((sqlite3_blob **)instanceData);
 
   zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
+  if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
+    return TCL_ERROR;
+  }
   rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
   if( rc!=SQLITE_OK ){
     Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index 746bfe4..9afeb11 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -12,7 +12,7 @@
 **
 ** This file contains code used to implement incremental BLOB I/O.
 **
-** $Id: vdbeblob.c,v 1.25 2008/07/28 19:34:54 drh Exp $
+** $Id: vdbeblob.c,v 1.26 2008/10/02 14:49:02 danielk1977 Exp $
 */
 
 #include "sqliteInt.h"
@@ -287,17 +287,17 @@
   Vdbe *v;
   sqlite3 *db = p->db;  
 
-  /* Request is out of range. Return a transient error. */
-  if( (iOffset+n)>p->nByte ){
-    return SQLITE_ERROR;
-  }
   sqlite3_mutex_enter(db->mutex);
-
-  /* If there is no statement handle, then the blob-handle has
-  ** already been invalidated. Return SQLITE_ABORT in this case.
-  */
   v = (Vdbe*)p->pStmt;
-  if( v==0 ){
+
+  if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
+    /* Request is out of range. Return a transient error. */
+    rc = SQLITE_ERROR;
+    sqlite3Error(db, SQLITE_ERROR, 0);
+  } else if( v==0 ){
+    /* If there is no statement handle, then the blob-handle has
+    ** already been invalidated. Return SQLITE_ABORT in this case.
+    */
     rc = SQLITE_ABORT;
   }else{
     /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is