stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r422914 - in /incubator/stdcxx/trunk/tests: self/0.printf.cpp src/printf.cpp
Date Mon, 17 Jul 2006 23:26:01 GMT
Author: sebor
Date: Mon Jul 17 16:26:00 2006
New Revision: 422914

URL: http://svn.apache.org/viewvc?rev=422914&view=rev
Log:
2006-07-17  Martin Sebor  <sebor@roguewave.com>

	* src/printf.cpp (_rw_bufcat): Avoided appending NUL to the end
	of buffer and failed consistently when the maximum size of of the
	buffer has been reached.
	(rw_vasnprintf): Allowed buffer length not including the terminating
	NUL to reach its maximum capacity. Reset errno to original value if
	set by a failed call to fprintf (e.g., when the file has been closed).
	(_rw_vasnprintf_ex): Made sure buffer is NUL-terminated before
	invoking user-defined callbacks.
	(rw_snprintfa): Returned (char*)0 on error.
	* test/printf.cpp (stress_bufsize): Stress test to exercised the
	ability to format into a fixed size buffer and correctly report
	buffer overlow errors via ENOMEM.
	(main): Closed stderr before calling stress_bufsize to avoid
	excessive noise.

Modified:
    incubator/stdcxx/trunk/tests/self/0.printf.cpp
    incubator/stdcxx/trunk/tests/src/printf.cpp

Modified: incubator/stdcxx/trunk/tests/self/0.printf.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/self/0.printf.cpp?rev=422914&r1=422913&r2=422914&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/self/0.printf.cpp (original)
+++ incubator/stdcxx/trunk/tests/self/0.printf.cpp Mon Jul 17 16:26:00 2006
@@ -32,6 +32,7 @@
 #include <ios>         // for ios::openmode, ios::seekdir
 #include <string>      // for string
 
+#include <assert.h>    // for assert()
 #include <ctype.h>     // for isdigit()
 #include <errno.h>     // for EXXX, errno
 #include <limits.h>    // for INT_MAX, ...
@@ -2703,6 +2704,51 @@
 
 /***********************************************************************/
 
+static void
+stress_bufsize ()
+{
+    // exercise the ability to format into a fixed size buffer
+    // and correctly report buffer overlow errors via ENOMEM
+
+    //////////////////////////////////////////////////////////////////
+    static const char str[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    char buf [sizeof str] = "";
+
+    for (unsigned size = 0; size != sizeof str - 1; ++size) {
+        for (unsigned len = 0; len != sizeof str - 1; ++len) {
+
+            errno = 0;
+
+            const char* const s = str + sizeof str - 1 - len;
+
+            // format a substring of s len characters long
+            // into a buffer size characters wide
+            const char* const res =
+                rw_snprintfa (buf, size, "%{*}%s", size, s);
+
+            const int error = errno;
+
+            if (size <= len) {
+                // verify that the function returns 0 and sets errno
+                // to ENOMEM when the provided buffer is not big enough
+                assert (0 == res);
+                assert (ENOMEM == error);
+            }
+            else {
+                // verify that the function returns the address
+                // of the provided buffer on success and that
+                // the contents of the buffer match the argument
+                assert (res == buf);
+                assert (0 == error);
+                assert (0 == strcmp (s, buf));
+            }
+        }
+    }
+}
+
+/***********************************************************************/
+
 int main ()
 {
     test_percent ();
@@ -2751,6 +2797,13 @@
                  nfailures, ntests);
         return 1;
     }
+
+    //////////////////////////////////////////////////////////////////
+    // close stderr to prevent the tested function from spitting out
+    // thousands of error messages in the stress test below
+    fclose (stderr);
+
+    stress_bufsize ();
 
     printf ("\nPassed all %d assertions.\n", ntests);
 

Modified: incubator/stdcxx/trunk/tests/src/printf.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/printf.cpp?rev=422914&r1=422913&r2=422914&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/printf.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/printf.cpp Mon Jul 17 16:26:00 2006
@@ -419,7 +419,7 @@
     size_t       buflen = buf.endoff;
     const size_t bufree = *buf.pbuf ? *buf.pbufsize - buflen : 0;
 
-    if (bufree <= len || !*buf.pbuf) {
+    if (bufree < len || !*buf.pbuf) {
 
         // for guard block
         static const char guard[] = "\xde\xad\xbe\xef";
@@ -465,14 +465,11 @@
 
         *buf.pbuf     = newbuf;
         *buf.pbufsize = newbufsize - guardsize;
-
-        (*buf.pbuf)[buflen] = '\0';
     }
 
     if (0 != str) {
         memcpy (*buf.pbuf + buflen, str, len);
         buflen += len;
-        (*buf.pbuf)[buflen] = '\0';
     }
 
     buf.endoff = buflen;
@@ -750,7 +747,7 @@
             goto fail;
 
         RW_ASSERT (0 != *buf.pbuf);
-        RW_ASSERT (0 != *buf.pbufsize);
+        RW_ASSERT (0 != buf.pbufsize);
 
         if (0 == pcnt)
             break;
@@ -843,8 +840,8 @@
             if (len < 0)
                 goto fail;
 
-            RW_ASSERT (size_t (len) < *buf.pbufsize);
-            RW_ASSERT (buf.endoff < *buf.pbufsize);
+            RW_ASSERT (size_t (len) <= *buf.pbufsize);
+            RW_ASSERT (buf.endoff <= *buf.pbufsize);
 
             const size_t offinx = size_t (nextoff - 1);
 
@@ -916,7 +913,7 @@
                 ++paramno;
             }
 
-            RW_ASSERT (len + buflen < *buf.pbufsize);
+            RW_ASSERT (len + buflen <= *buf.pbufsize);
 
             // adjust the next pointer to point to the terminating
             // NUL in the (possibly reallocated) buffer
@@ -975,10 +972,12 @@
 
 fail: // function failed
 
+    const int error = errno;
+
     fprintf (stderr, "%s:%d: rw_vasnprintf(%p, %p, \"%s\", va_list) "
              "error: errno = %d: %s\n",
              __FILE__, __LINE__, (void*)buf.pbuf, (void*)buf.pbufsize, fmt,
-             errno, strerror (errno));
+             error, strerror (error));
 
     for (size_t i = 0; i != paramno; ++i)
         free (pspec [i].strarg);
@@ -992,6 +991,9 @@
         *buf.pbuf = 0;
     }
 
+    if (errno != error)
+        errno = error;
+
     return -1;
 
 #undef varg
@@ -2445,6 +2447,11 @@
         // top to bottom
 
         if (_rw_usr_fun [i]) {
+            if (0 == _rw_bufcat (buf, 0, 1))
+                return -1;
+
+            (*buf.pbuf)[buf.endoff] = '\0';
+
             // user-defined extension?
             if (0 < spec.paramno) {
                 // pass the address of the paramno argument
@@ -3094,7 +3101,7 @@
 
     _RWSTD_UNUSED (nchars);
 
-    return buf;
+    return nchars < 0 ? 0 : buf;
 }
 
 /********************************************************************/



Mime
View raw message