Sender: richdawe AT bigfoot DOT com Message-ID: <3A132065.9FA6E06B@bigfoot.com> Date: Wed, 15 Nov 2000 23:46:45 +0000 From: Richard Dawe X-Mailer: Mozilla 4.51 [en] (X11; I; Linux 2.2.17 i586) X-Accept-Language: de,fr MIME-Version: 1.0 To: DJGPP workers Subject: snprintf() diff, take 2 Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="------------ms1424A44FEF052BAD90FA7479" Reply-To: djgpp-workers AT delorie DOT com This is a cryptographically signed message in MIME format. --------------ms1424A44FEF052BAD90FA7479 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hello. Here is a second diff for the snprintf() code. This supercedes the previous one. Changes from the previous version: * __putc_raw() now returns the character that would have been stuffed into the buffer, if had there been space. Previously it returned 0. The change restores the semantics of __putc_raw() the full string buffer case. * I added a note on the maximum value of 'n' for snprintf(), vsnprintf(). The value of errno is not documented, since errno is only set for the case where n is too big. This seems to be OK according to the C spec - we can set errno to whatever we like, since snprintf() does not have a defined effect on errno. * Fixed a couple of format warnings in the test. Bye, Rich *** /develop/djgpp/include/libc/file.h Sun Jun 27 17:27:44 1999 --- /develop/djgpp.dev/include/libc/file.h Wed Nov 15 22:38:38 2000 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ *************** static __inline__ int __putc_raw(int con *** 52,57 **** --- 53,63 ---- { p->_cnt--; return((unsigned char)(*(p->_ptr++)=(unsigned char)x)); + } + else if (p->_flag & _IOSTRG) + { + /* noop for full string buffers */ + return((unsigned char)x); } return(_flsbuf((unsigned char)x,p)); } *** /develop/djgpp/include/stdio.h Sun Nov 15 13:37:28 1998 --- /develop/djgpp.dev/include/stdio.h Sun Nov 12 21:18:46 2000 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ *************** void rewind(FILE *_stream); *** 94,99 **** --- 95,101 ---- int scanf(const char *_format, ...); void setbuf(FILE *_stream, char *_buf); int setvbuf(FILE *_stream, char *_buf, int _mode, size_t _size); + int snprintf(char *str, size_t n, const char *fmt, ...); int sprintf(char *_s, const char *_format, ...); int sscanf(const char *_s, const char *_format, ...); FILE * tmpfile(void); *************** char * tmpnam(char *_s); *** 101,106 **** --- 103,109 ---- int ungetc(int _c, FILE *_stream); int vfprintf(FILE *_stream, const char *_format, va_list _ap); int vprintf(const char *_format, va_list _ap); + int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); int vsprintf(char *_s, const char *_format, va_list _ap); #ifndef __STRICT_ANSI__ *** /develop/djgpp/src/docs/kb/wc204.txi Fri Oct 6 23:53:22 2000 --- /develop/djgpp.dev/src/docs/kb/wc204.txi Sun Nov 12 21:34:42 2000 *************** pollute the name space with the symbols *** 131,133 **** --- 131,136 ---- @code{end}. The profiling code was also changed to not pollute the name space with @code{etext}. + @findex snprintf + @findex vsnprintf + New functions @code{snprintf} and @code{vsnprintf} added. *** /develop/djgpp/src/libc/ansi/stdio/makefile Sun Jun 28 18:44:16 1998 --- /develop/djgpp.dev/src/libc/ansi/stdio/makefile Sun Nov 12 21:57:50 2000 *************** *** 1,3 **** --- 1,4 ---- + # Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details # Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details # Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details TOP=../.. *************** SRC += ungetc.c *** 61,65 **** --- 62,68 ---- SRC += vfprintf.c SRC += vprintf.c SRC += vsprintf.c + SRC += snprintf.c + SRC += vsnprntf.c include $(TOP)/../makefile.inc *** /develop/djgpp/src/libc/ansi/stdio/snprintf.c Sun Nov 12 21:57:18 2000 --- /develop/djgpp.dev/src/libc/ansi/stdio/snprintf.c Sun Nov 12 21:58:06 2000 *************** *** 1 **** --- 1,28 ---- + /* Copyright (C) 2000 DJ Delorie see COPYING.DJ for details */ + #include + #include + #include + #include + int + snprintf(char *str, size_t n, const char *fmt, ...) + { + FILE _strbuf; + int len; + + /* _cnt is an int in the FILE structure. To prevent wrap-around, we limit + * n to between 0 and INT_MAX inclusively. */ + if (n > INT_MAX) + { + errno = EFBIG; + return -1; + } + + _strbuf._flag = _IOWRT | _IOSTRG | _IONTERM; + _strbuf._ptr = str; + _strbuf._cnt = n - 1; + len = _doprnt(fmt, &(fmt)+1, &_strbuf); + if (n != 0) + *_strbuf._ptr = 0; + return len; + } *** /develop/djgpp/src/libc/ansi/stdio/snprintf.txh Sun Nov 12 21:57:18 2000 --- /develop/djgpp.dev/src/libc/ansi/stdio/snprintf.txh Wed Nov 15 22:36:34 2000 *************** *** 1 **** --- 1,27 ---- + @node snprintf, stdio + @subheading Syntax + @example + #include + + int snprintf (char *@var{buffer}, size_t @var{n}, const char *@var{format}, + @dots{}); + @end example + + @subheading Description + + This function works similarly to @xref{sprintf}, but the size @var{n} of + the @var{buffer} is also taken into account. This function will write + @var{n} - 1 characters. The @var{n}th character is used for the terminating + nul. If @var{n} is zero, @var{buffer} is not touched. + + @subheading Return Value + + The number of characters that would have been written (excluding the trailing + nul) is returned; otherwise -1 is returned to flag encoding errors. + + @subheading Portability + + @port-note ansi For DJGPP, the maximum accepted value of @var{n} is INT_MAX. An error is returned if @var{n} is greater than this limit. + + @portability ansi \ No newline at end of file *** /develop/djgpp/src/libc/ansi/stdio/sprintf.txh Sun Sep 27 16:20:50 1998 --- /develop/djgpp.dev/src/libc/ansi/stdio/sprintf.txh Sun Nov 12 21:37:08 2000 *************** int sprintf(char *buffer, const char *fo *** 12,17 **** --- 12,20 ---- Sends formatted output from the arguments (@dots{}) to the @var{buffer}. @xref{printf}. + To avoid buffer overruns, it is safer to use @code{snprintf()} + (@pxref{snprintf}). + @subheading Return Value The number of characters written. *** /develop/djgpp/src/libc/ansi/stdio/vsnprntf.c Sun Nov 12 21:57:18 2000 --- /develop/djgpp.dev/src/libc/ansi/stdio/vsnprntf.c Sun Nov 12 21:58:16 2000 *************** *** 1 **** --- 1,29 ---- + /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + #include + #include + #include + #include + #include + int + vsnprintf(char *str, size_t n, const char *fmt, va_list ap) + { + FILE _strbuf; + int len; + + /* _cnt is an int in the FILE structure. To prevent wrap-around, we limit + * n to between 0 and INT_MAX inclusively. */ + if (n > INT_MAX) + { + errno = EFBIG; + return -1; + } + + _strbuf._flag = _IOWRT | _IOSTRG | _IONTERM; + _strbuf._ptr = str; + _strbuf._cnt = n - 1; + len = _doprnt(fmt, ap, &_strbuf); + if (n != 0) + *_strbuf._ptr = 0; + return len; + } *** /develop/djgpp/src/libc/ansi/stdio/vsnprntf.txh Sun Nov 12 21:57:18 2000 --- /develop/djgpp.dev/src/libc/ansi/stdio/vsnprntf.txh Wed Nov 15 22:36:54 2000 *************** *** 1 **** --- 1,28 ---- + @node vsnprintf, stdio + @subheading Syntax + @example + #include + #include + + int vsnprintf (char *@var{buffer}, size_t @var{n}, const char *@var{format}, + va_list @var{ap}); + @end example + + @subheading Description + + This function works similarly to @xref{vsprintf}, but the size @var{n} of + the @var{buffer} is also taken into account. This function will write + @var{n} - 1 characters. The @var{n}th character is used for the terminating + nul. If @var{n} is zero, @var{buffer} is not touched. + + @subheading Return Value + + The number of characters that would have been written (excluding the trailing + nul) is returned; otherwise -1 is returned to flag encoding errors. + + @subheading Portability + + @port-note ansi For DJGPP, the maximum accepted value of @var{n} is INT_MAX. An error is returned if @var{n} is greater than this limit. + + @portability ansi *** /develop/djgpp/src/libc/ansi/stdio/vsprintf.txh Sun Sep 27 16:20:50 1998 --- /develop/djgpp.dev/src/libc/ansi/stdio/vsprintf.txh Sun Nov 12 21:37:00 2000 *************** int vsprintf(char *buffer, const char *f *** 13,18 **** --- 13,21 ---- Sends formatted output from the @var{arguments} to the @var{buffer}. @xref{printf}. @xref{vfprintf}. + To avoid buffer overruns, it is safer to use @code{vsnprintf()} + (@pxref{vsnprintf}). + @subheading Return Value The number of characters written. *** /develop/djgpp/tests/libc/ansi/stdio/snprintf.c Sun Nov 12 21:57:18 2000 --- /develop/djgpp.dev/tests/libc/ansi/stdio/snprintf.c Wed Nov 15 22:41:26 2000 *************** *** 1 **** --- 1,58 ---- + #include + int main () + { + char holder[24]; + unsigned i, j; + + #define BIG "Hello this is a too big string for the buffer" + i = snprintf (holder, sizeof (holder), "%s\n", BIG); + printf ("%s\n", BIG); + printf ("%s\n", holder); + /* + * We are expecting : + * i == strlen (BIG) + 1 + * meaning the number that would have been written if the buffer was + * large enough (see C9X). + */ + if (i != strlen (BIG) + 1/* NL */) + { + fprintf (stderr, "FAILED snprintf\n"); + fprintf (stderr, + "sizeof (%ld), snprintf(%d), strlen(%ld)\n", + sizeof (holder), i, strlen (BIG)) ; + exit (1); + } + + /* We may have broken sscanf since it is also a string stream + * Lets do a basic test. + */ + { + static char *line = "25 December 2000\n"; + int day, year; + char month[24]; + + /* we are expectinc to read 3 variables */ + if ((i = sscanf (line, "%d %s %d\n", &day, month, &year)) == 3) + { + i = snprintf (holder, sizeof(holder), "%d %s %d\n", day, month, year); + printf (line); + j = printf (holder); + if (i != j) + { + fprintf (stderr, "FAILED snprintf\n"); + fprintf (stderr, "snprintf (%d) != printf (%d)\n", i, j); + exit (1); + } + } + else + { + printf ("sscanf (%d)\n", i); + printf ("FAILED sscanf\n"); + exit (1); + } + } + /* signal success */ + printf ("SUCCESS\n"); + return 0; + } --------------ms1424A44FEF052BAD90FA7479 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: S/MIME Cryptographic Signature MIIHFQYJKoZIhvcNAQcCoIIHBjCCBwICAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC BY0wggLMMIICNaADAgECAhB2D2twnX9wqhegGKLtJkJmMA0GCSqGSIb3DQEBBAUAMFgxJzAl BgNVBAoTHkJyaXRpc2ggVGVsZWNvbW11bmljYXRpb25zIHBsYzEtMCsGA1UECxMkQlQgVHJ1 c3R3aXNlIC0gQ2xhc3MgMSBJbmRpdmlkdWFsIENBMB4XDTAwMTAxNTAwMDAwMFoXDTAxMTAx NTIzNTk1OVowggERMScwJQYDVQQKEx5Ccml0aXNoIFRlbGVjb21tdW5pY2F0aW9ucyBwbGMx LTArBgNVBAsTJEJUIFRydXN0d2lzZSAtIENsYXNzIDEgSW5kaXZpZHVhbCBDQTFGMEQGA1UE CxM9d3d3LnRydXN0d2lzZS5jb20vcmVwb3NpdG9yeS9SUCBJbmNvcnAuIGJ5IFJlZi4sTElB Qi5MVEQoYyk5ODEzMDEGA1UECxMqRGlnaXRhbCBJRCBDbGFzcyAxIC0gTmV0c2NhcGUgRnVs bCBTZXJ2aWNlMRUwEwYDVQQDEwxSaWNoYXJkIERhd2UxIzAhBgkqhkiG9w0BCQEWFHJpY2hk YXdlQGJpZ2Zvb3QuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMJ3LQ1fxlYpzsChuJ16 J9dwyZIkhexC8uW2RGyxJVOG6643weIDoATk515qu8G91CS85rLDRFIB0u2N4ezCUCkCAwEA AaMgMB4wCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCB4AwDQYJKoZIhvcNAQEEBQADgYEA llCoL5Afa66m9bxGh/gMgwUCCCOb6DdKHmJw9Q5h0xoEHuHOcEEjNPqQug5ZQaKioEIJM7DS gsuSPrEy5Z521OzNWxN8nRv9YAlV3fVHQxcNlsjaAZru6zJxZ0+0uAKKFKOjJLTdfXFUqdcH kcY2syIZo6DRSIap9pCqC+HYOoIwggK5MIICIqADAgECAhEA0zBJnvKZLVDb03kHStQNPTAN BgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4x NzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkwHhcNOTgwMjEyMDAwMDAwWhcNMDMwMjEyMjM1OTU5WjBYMScwJQYDVQQKEx5Ccml0aXNo IFRlbGVjb21tdW5pY2F0aW9ucyBwbGMxLTArBgNVBAsTJEJUIFRydXN0d2lzZSAtIENsYXNz IDEgSW5kaXZpZHVhbCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0QG30oEW28L0 Z/5fC03tfZ+a2ahBQYehZ6hrcb1PW6ZIXuqm5y8KpzYJ9rLhRkMA3BzH8eACTVhkn/qAJmqC m2GTDa7eueV8q6A/0I/p9KwahkjEgG4exysZ9svlo21+HWn0yFtrHAraKuNoZOPpFnNP5dOp AuObV5lKytU5AlkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEGMEcGA1UdIARAMD4wPAYL YIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNvbS9yZXBvc2l0b3J5 L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQIFAAOBgQBS Acma9vqkvYS4miXj6t5jPDVao9pIjdxWTjRoiRPRRi7wz0On9jUzqVK8sVcrPIpwxmvnlOyv jM8KpZaJVXECrgclfNlGR58eSiyTSHyBO0XUK4XLJkwkBXyBmiHc+32l5gvC+QXuGccUEdg8 WZ/OOeoRMbCdGuw1+LeE55h4JzGCAVAwggFMAgEBMGwwWDEnMCUGA1UEChMeQnJpdGlzaCBU ZWxlY29tbXVuaWNhdGlvbnMgcGxjMS0wKwYDVQQLEyRCVCBUcnVzdHdpc2UgLSBDbGFzcyAx IEluZGl2aWR1YWwgQ0ECEHYPa3Cdf3CqF6AYou0mQmYwCQYFKw4DAhoFAKB9MBgGCSqGSIb3 DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTAwMTExNTIzNDY0NVowHgYJKoZI hvcNAQkPMREwDzANBggqhkiG9w0DAgIBKDAjBgkqhkiG9w0BCQQxFgQUoyWMqqTC2OlJiyyj v12V09/mA7YwDQYJKoZIhvcNAQEBBQAEQHPEs80Lh5fXowzEVbF3y9htir/6sv5i0GL/jCxW Z+OiNEC6UAGT/kPptnOTtREuVKNcsJLt0MNtyRrxiN0U6XU= --------------ms1424A44FEF052BAD90FA7479--