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)

FossilOrigin-Name: f3ae4ac5fe0bfa2f91e76a6def86c444e51fe80b
This commit is contained in:
drh 2007-05-07 11:24:30 +00:00
parent a9808b31a8
commit 6885390791
7 changed files with 83 additions and 19 deletions

View File

@ -65,8 +65,6 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.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 = \
@ -143,8 +141,6 @@ SRC += \
$(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
#

View File

@ -1,5 +1,5 @@
C Add\sthe\sexperimental\screate_collation_x()\sapi.\s(CVS\s3934)
D 2007-05-07T09:32:45
C Change\ssqlite3_snprintf()\sso\sthat\sit\sdoes\snot\swrite\sa\szero-terminator\sif\nthe\sbuffer\ssize\sargument\sis\sless\sthan\s1.\s\sTicket\s#2341.\s\sAdded\sdocumentation\nabout\sthe\ssqlite3_snprintf()\sfunction.\s(CVS\s3935)
D 2007-05-07T11:24:30
F Makefile.in ea8888bdcf53313d26576fcabcb6d0a10ecd35cd
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -46,7 +46,7 @@ F ext/fts2/mkfts2amal.tcl 2a9ec76b0760fe7f3669dca5bc0d60728bc1c977
F ext/icu/icu.c a30999ba467749ed6232d02cc8c4b5a0e62cd727
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh 56abb507100ed2d4261f6dd1653dec3cf4066387
F main.mk 6298bd3fcbc590fe05354f7d962c57ac202d7bcd
F main.mk 09c19ae05ac9e5654d5fd866a980b21ad9df8f30
F mkdll.sh ed62756baf44babf562a7843588790c02fee2106
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
F mkopcodeh.awk cde995d269aa06c94adbf6455bea0acedb913fa5
@ -96,7 +96,7 @@ F src/pager.h d652ddf092d2318d00e41f8539760fe8e57c157c
F src/parse.y a5bdc301e970ceb3826b56a84898b8966d5353f8
F src/pragma.c 3f16c1274bc25afb630b61a3630ea19a2fd0b5dc
F src/prepare.c 03277063bc4f5860efbf23548fa0123ac0f6eaec
F src/printf.c 0c6f40648770831341ac45ab32423a80b4c87f05
F src/printf.c 67de0dcb40ef3297f4a047b434b81585c0f7062d
F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
F src/select.c a306d03fc7d8365055bef70c3563e8fca897460f
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
@ -106,7 +106,7 @@ F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890
F src/sqliteInt.h 5e1cf645ef1bf8b43c5d020adbeed43746df24ed
F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
F src/tclsqlite.c f3414b2d6bc37e6760b49c9abd3504ff69f4441b
F src/test1.c a91c84e903e3a59ad3bf6c10bd5b93e74d631ea2
F src/test1.c 84e78efa05a6d36a1868912b84cc5009d990f49d
F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
F src/test3.c 946ea9d1a8c928656e3c70f0a2fcb8e733a15e86
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
@ -309,7 +309,7 @@ F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
F test/pageropt.test b4b38eb3cf76be2be444326856248898bb0e3fc9
F test/pagesize.test e0a8b3fe80f8b8e808d94a00734c7a18c76c407e
F test/pragma.test fecb7085f58d9fb5172a5c0b63fd3b25c7bfb414
F test/printf.test 483b9fe75ffae1fb27328bdce5560b452ba83577
F test/printf.test 71047b5fe8e2adfbe514e0d56e10adf12d84deff
F test/progress.test 8b22b4974b0a95272566385f8cb8c341c7130df8 x
F test/ptrchng.test 1c712dd6516e1377471744fa765e41c79a357da6
F test/quick.test afa4339d08800d8aa3625df6cc2f059cc505f4c3
@ -437,7 +437,7 @@ F www/audit.tcl 90e09d580f79c7efec0c7d6f447b7ec5c2dce5c0
F www/autoinc.tcl b357f5ba954b046ee35392ce0f884a2fcfcdea06
F www/c_interface.tcl b51b08591554c16a0c3ef718364a508ac25abc7e
F www/capi3.tcl 88884dd743039d1a95aa57f4a5eb369de7744716
F www/capi3ref.tcl 0d742d6bd59bc51bbb4be014e7ea47e97786d318
F www/capi3ref.tcl be09756d8b9aebd2d7b597fb910eed66fb4480e6
F www/changes.tcl 550300b0ff00fc1b872f7802b2d5a1e7587d3e58
F www/common.tcl 2b793e5c31486c8a01dd27dc0a631ad93704438e
F www/compile.tcl 276546d7eb445add5a867193bbd80f6919a6b084
@ -481,7 +481,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P 2d1348dda2cbdf958a15267432063f359550c303
R cb3c4e9539473867932a2c5f74528890
U danielk1977
Z eaa2b3011ed3cbd2140fcff678e040f6
P ff49d48f2f025898a0f4ace1fc227e1d367ea89f
R d693f630962da031deefd4769c7a8268
U drh
Z ff527a494f455c458a9191e7c78f4220

View File

@ -1 +1 @@
ff49d48f2f025898a0f4ace1fc227e1d367ea89f
f3ae4ac5fe0bfa2f91e76a6def86c444e51fe80b

View File

@ -837,6 +837,10 @@ 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);

View File

@ -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.248 2007/05/07 09:32:45 danielk1977 Exp $
** $Id: test1.c,v 1.249 2007/05/07 11:24:30 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -426,6 +426,33 @@ static int test_mprintf_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
**
@ -4609,6 +4636,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "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 },

View File

@ -11,7 +11,7 @@
# 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 $
# $Id: printf.test,v 1.23 2007/05/07 11:24:31 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -268,5 +268,14 @@ 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

View File

@ -1,4 +1,4 @@
set rcsid {$Id: capi3ref.tcl,v 1.56 2007/04/27 17:16:22 drh Exp $}
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 {
@ -1134,6 +1134,33 @@ char *sqlite3_vmprintf(const char*, va_list);
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) */