]> Savannah Git Hosting - gnulib.git/commitdiff
quotearg: never write beyond the returned length
authorPádraig Brady <pbrady@fb.com>
Tue, 18 Oct 2016 20:00:07 +0000 (13:00 -0700)
committerPádraig Brady <pbrady@fb.com>
Wed, 19 Oct 2016 13:52:57 +0000 (06:52 -0700)
* lib/quotearg.c (quotearg_buffer_restyled): Switch to a read-only
scan of the string when we initially encounter a single quote when
shell quoting, so that if we then switch to a more concise quoting method
we will not have written beyond that returned length.
This is significant for sh-quote, which has separate routines
to determine the length and do the actual quoting.
* tests/test-quotearg.h: Reinstate the buffer bounds checking
now that we never write more than the returned length.

ChangeLog
lib/quotearg.c
tests/test-quotearg.h

index 08ad0fdc046750eff73b683ce545e73d29245eb1..48f718007d7501a2ec6fb4db207b11d2018174e1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2016-10-19  Pádraig Brady  <P@draigBrady.com>
+
+       quotearg: never write beyond the returned length
+       * lib/quotearg.c (quotearg_buffer_restyled): Switch to a read-only
+       scan of the string when we initially encounter a single quote when
+       shell quoting, so that if we then switch to a more concise quoting method
+       we will not have written beyond that returned length.
+       This is significant for sh-quote, which has separate routines
+       to determine the length and do the actual quoting.
+       * tests/test-quotearg.h: Reinstate the buffer bounds checking
+       now that we never write more than the returned length.
+
 2016-10-18  Bruno Haible  <bruno@clisp.org>
 
        getprogname tests: Avoid failure in packages that use libtool.
index 4009073b093bb7878a9c73e437d0b6a354667dac..730b4b38d7f5906d5a5aaef5b6864c22a658c8af 100644 (file)
@@ -252,6 +252,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
 {
   size_t i;
   size_t len = 0;
+  size_t orig_buffersize = 0;
   char const *quote_string = 0;
   size_t quote_string_len = 0;
   bool backslash_escapes = false;
@@ -300,6 +301,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
       } \
     while (0)
 
+ process_input:
+
   switch (quoting_style)
     {
     case c_maybe_quoting_style:
@@ -544,6 +547,16 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
             {
               if (elide_outer_quotes)
                 goto force_outer_quoting_style;
+
+              if (buffersize && ! orig_buffersize)
+                {
+                  /* Just scan string to see if supports a more concise
+                     representation, rather than writing a longer string
+                     but returning the length of the more concise form.  */
+                  orig_buffersize = buffersize;
+                  buffersize = 0;
+                }
+
               STORE ('\'');
               STORE ('\\');
               STORE ('\'');
@@ -713,11 +726,21 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
      better to use the apostrophe modifier "\u02BC" if possible, as that
      renders better and works with the word match regex \W+ etc.  */
   if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
-      && all_c_and_shell_quote_compat && encountered_single_quote)
-    return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
-                                     c_quoting_style,
-                                     flags, quote_these_too,
-                                     left_quote, right_quote);
+      && encountered_single_quote)
+    {
+      if (all_c_and_shell_quote_compat)
+        return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
+                                         c_quoting_style,
+                                         flags, quote_these_too,
+                                         left_quote, right_quote);
+      else if (! buffersize && orig_buffersize)
+        {
+          /* Disable read-only scan, and reprocess to write quoted string.  */
+          buffersize = orig_buffersize;
+          len = 0;
+          goto process_input;
+        }
+    }
 
   if (quote_string && !elide_outer_quotes)
     for (; *quote_string; quote_string++)
index 8fb1fd9030031f7c88fe75c179612d101a27c794..1de74368d2825f484a53748a4166f6b32cd463c8 100644 (file)
@@ -104,10 +104,9 @@ use_quotearg_buffer (const char *str, size_t *len)
   static char buf[100];
   size_t size;
   memset (buf, 0xa5, 100);
-  size = quotearg_buffer (buf, 50, str, *len, NULL);
+  size = quotearg_buffer (buf, 100, str, *len, NULL);
   *len = size;
-  ASSERT ((unsigned char) buf[size] == '\0');
-  ASSERT ((unsigned char) buf[50] == 0xa5);
+  ASSERT ((unsigned char) buf[size + 1] == 0xa5);
   return buf;
 }