/ Check-in [f3ae4ac5]
Login

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

Overview
Comment:Change sqlite3_snprintf() so that it does not write a zero-terminator if the buffer size argument is less than 1. Ticket #2341. Added documentation about the sqlite3_snprintf() function. (CVS 3935)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f3ae4ac5fe0bfa2f91e76a6def86c444e51fe80b
User & Date: drh 2007-05-07 11:24:30
Context
2007-05-07
11:53
Add interface to configure SQLite to use ICU collation functions. (CVS 3936) check-in: b29a81b4 user: danielk1977 tags: trunk
11:24
Change sqlite3_snprintf() so that it does not write a zero-terminator if the buffer size argument is less than 1. Ticket #2341. Added documentation about the sqlite3_snprintf() function. (CVS 3935) check-in: f3ae4ac5 user: drh tags: trunk
09:32
Add the experimental create_collation_x() api. (CVS 3934) check-in: ff49d48f user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
         main.o malloc.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
         pager.o parse.o pragma.o prepare.o printf.o random.o \
         select.o table.o tclsqlite.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o vtab.o

LIBOBJ += icu.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/alter.c \
  $(TOP)/src/analyze.c \
  $(TOP)/src/attach.c \
  $(TOP)/src/auth.c \
................................................................................
  $(TOP)/ext/fts2/fts2.c \
  $(TOP)/ext/fts2/fts2.h \
  $(TOP)/ext/fts2/fts2_hash.c \
  $(TOP)/ext/fts2/fts2_hash.h \
  $(TOP)/ext/fts2/fts2_porter.c \
  $(TOP)/ext/fts2/fts2_tokenizer.h \
  $(TOP)/ext/fts2/fts2_tokenizer1.c
SRC += \
  $(TOP)/ext/icu/icu.c

# Generated source code files
#
SRC += \
  keywordhash.h \
  opcodes.c \
  opcodes.h \







<
<







 







<
<







61
62
63
64
65
66
67


68
69
70
71
72
73
74
...
137
138
139
140
141
142
143


144
145
146
147
148
149
150
         main.o malloc.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
         pager.o parse.o pragma.o prepare.o printf.o random.o \
         select.o table.o tclsqlite.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o vtab.o



# All of the source code files.
#
SRC = \
  $(TOP)/src/alter.c \
  $(TOP)/src/analyze.c \
  $(TOP)/src/attach.c \
  $(TOP)/src/auth.c \
................................................................................
  $(TOP)/ext/fts2/fts2.c \
  $(TOP)/ext/fts2/fts2.h \
  $(TOP)/ext/fts2/fts2_hash.c \
  $(TOP)/ext/fts2/fts2_hash.h \
  $(TOP)/ext/fts2/fts2_porter.c \
  $(TOP)/ext/fts2/fts2_tokenizer.h \
  $(TOP)/ext/fts2/fts2_tokenizer1.c



# Generated source code files
#
SRC += \
  keywordhash.h \
  opcodes.c \
  opcodes.h \

Changes to src/printf.c.

833
834
835
836
837
838
839




840
841
842
843
844
845
846
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
  char *z;
  va_list ap;





  va_start(ap,zFormat);
  z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
  va_end(ap);
  return z;
}

#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)







>
>
>
>







833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
  char *z;
  va_list ap;

  if( n<=0 ){
    return zBuf;
  }
  zBuf[0] = 0;
  va_start(ap,zFormat);
  z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
  va_end(ap);
  return z;
}

#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
421
422
423
424
425
426
427



























428
429
430
431
432
433
434
....
4605
4606
4607
4608
4609
4610
4611

4612
4613
4614
4615
4616
4617
4618
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.248 2007/05/07 09:32:45 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  char *zStr;
  int n = 0;
  zStr = sqlite3MPrintf("%s%n", argv[1], &n);
  sqliteFree(zStr);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
  return TCL_OK;
}




























/*
** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING
**
** Invoke the sqlite3_get_table_printf() interface using the open database
** DB.  The SQL is the string FORMAT.  The format string should contain
** one %s or %q.  STRING is the value inserted into %s or %q.
................................................................................
     { "sqlite3_snprintf_str",          (Tcl_CmdProc*)sqlite3_snprintf_str   },
     { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
     { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
     { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
     { "sqlite3_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
     { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
     { "sqlite3_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },

     { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite3_exec",                  (Tcl_CmdProc*)test_exec             },
     { "sqlite3_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
     { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
     { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },







|







 







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







 







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
....
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing all sorts of SQLite interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.249 2007/05/07 11:24:30 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  char *zStr;
  int n = 0;
  zStr = sqlite3MPrintf("%s%n", argv[1], &n);
  sqliteFree(zStr);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
  return TCL_OK;
}

/*
** Usage:  sqlite3_snprintf_int  SIZE FORMAT  INT
**
** Test the of sqlite3_snprintf() routine.  SIZE is the size of the
** output buffer in bytes.  The maximum size is 100.  FORMAT is the
** format string.  INT is a single integer argument.  The FORMAT
** string must require no more than this one integer argument.  If
** You pass in a format string that requires more than one argument,
** bad things will happen.
*/
static int test_snprintf_int(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  char zStr[100];
  int n = atoi(argv[1]);
  if( n>sizeof(zStr) ) n = sizeof(zStr);
  const char *zFormat = argv[2];
  int a1 = atoi(argv[3]);
  strcpy(zStr, "abcdefghijklmnopqrstuvwxyz");
  sqlite3_snprintf(n, zStr, zFormat, a1);
  Tcl_AppendResult(interp, zStr, 0);
  return TCL_OK;
}

/*
** Usage:  sqlite3_get_table_printf  DB  FORMAT  STRING
**
** Invoke the sqlite3_get_table_printf() interface using the open database
** DB.  The SQL is the string FORMAT.  The format string should contain
** one %s or %q.  STRING is the value inserted into %s or %q.
................................................................................
     { "sqlite3_snprintf_str",          (Tcl_CmdProc*)sqlite3_snprintf_str   },
     { "sqlite3_mprintf_stronly",       (Tcl_CmdProc*)sqlite3_mprintf_stronly},
     { "sqlite3_mprintf_double",        (Tcl_CmdProc*)sqlite3_mprintf_double },
     { "sqlite3_mprintf_scaled",        (Tcl_CmdProc*)sqlite3_mprintf_scaled },
     { "sqlite3_mprintf_hexdouble",   (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
     { "sqlite3_mprintf_z_test",        (Tcl_CmdProc*)test_mprintf_z        },
     { "sqlite3_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
     { "sqlite3_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },
     { "sqlite3_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite3_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite3_exec",                  (Tcl_CmdProc*)test_exec             },
     { "sqlite3_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
     { "sqlite3_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
     { "sqlite3_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite3_create_function",       (Tcl_CmdProc*)test_create_function  },

Changes to test/printf.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
264
265
266
267
268
269
270









271
272
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.22 2007/03/31 15:02:50 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  set v32 [expr {$v&0xffffffff}]
................................................................................
do_test printf-14.2 {
  sqlite3_mprintf_n_test {xyzzy}
} 5
do_test printf-14.3 {
  sqlite3_mprintf_str {abc-%T-123} 0 0 {not used}
} {abc-}











finish_test







|







 







>
>
>
>
>
>
>
>
>


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.23 2007/05/07 11:24:31 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  set v32 [expr {$v&0xffffffff}]
................................................................................
do_test printf-14.2 {
  sqlite3_mprintf_n_test {xyzzy}
} 5
do_test printf-14.3 {
  sqlite3_mprintf_str {abc-%T-123} 0 0 {not used}
} {abc-}

do_test printf-15.1 {
  sqlite3_snprintf_int 5 {12345} 0
} {1234}
do_test printf-15.2 {
  sqlite3_snprintf_int 5 {} 0
} {}
do_test printf-15.3 {
  sqlite3_snprintf_int 0 {} 0
} {abcdefghijklmnopqrstuvwxyz}

finish_test

Changes to www/capi3ref.tcl.

1
2
3
4
5
6
7
8
....
1129
1130
1131
1132
1133
1134
1135



























1136
1137
1138
1139
1140
1141
1142
set rcsid {$Id: capi3ref.tcl,v 1.56 2007/04/27 17:16:22 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2 class=pdf_section>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
................................................................................
  INSERT INTO table1 VALUES('It's a happy day!');
  </pre></blockquote>

 This second example is an SQL syntax error.  As a general rule you
 should always use %q instead of %s when inserting text into a string 
 literal.
} {}




























api {} {
int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
int sqlite3_open16(
|







 







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







1
2
3
4
5
6
7
8
....
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
set rcsid {$Id: capi3ref.tcl,v 1.57 2007/05/07 11:24:31 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2 class=pdf_section>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
................................................................................
  INSERT INTO table1 VALUES('It's a happy day!');
  </pre></blockquote>

 This second example is an SQL syntax error.  As a general rule you
 should always use %q instead of %s when inserting text into a string 
 literal.
} {}

api {} {
char *sqlite3_snprintf(int bufSize, char *buf, const char *zFormat, ...);
} {
  This routine works like "sprintf()", writing a formatted string into
  the buf[].  However, no more than bufSize characters will be written
  into buf[].  This routine returns a pointer to buf[].  If bufSize is
  greater than zero, then buf[] is guaranteed to be zero-terminated.

  This routine uses the same extended formatting options as
  sqlite3_mprintf() and sqlite3_vmprintf().

  Note these differences with the snprintf() function found in many
  standard libraries:  (1)  sqlite3_snprintf() returns a pointer to the
  buffer rather than the number of characters written.  (It would,
  arguably, be more useful to return the number of characters written,
  but we discovered that after the interface had been published and
  are unwilling to break backwards compatibility.)  (2)  The order
  of the bufSize and buf parameter is reversed from snprintf().  
  And (3) sqlite3_snprintf() always writes a zero-terminator if bufSize
  is positive.  

  Please do not use the return value of this routine.  We may
  decide to make the minor compatibility break and change this routine
  to return the number of characters written rather than a pointer to
  the buffer in a future minor version increment.
}

api {} {
int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
int sqlite3_open16(