diffutils-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 15/17] diff: avoid sprintf %s


From: Paul Eggert
Subject: [PATCH 15/17] diff: avoid sprintf %s
Date: Sun, 22 Aug 2021 14:03:04 -0700

sprintf fails if the result contains more than INT_MAX bytes,
so rework the code to avoid usage of sprintf %s where the
string might be longer than that.
* bootstrap.conf (gnulib_modules): Remove xvasprintf.
* src/diff.c (specify_style):
* src/util.c (begin_output):
Rewrite to avoid sprintf %s.
* src/util.c: Do not include xvasprintf.h.
(concat): Remove, as it uses sprintf %s.  All uses rewritten.
---
 bootstrap.conf |  1 -
 src/diff.c     | 72 ++++++++++++++++++++++++++++++++++++++------------
 src/diff.h     |  3 ---
 src/util.c     | 20 ++++++--------
 4 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index b3c39e6..6560e9a 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -93,7 +93,6 @@ xmalloca
 xreadlink
 xstdopen
 xstrtoimax
-xvasprintf
 '
 
 # Additional xgettext options to use.  Use "\\\newline" to break lines.
diff --git a/src/diff.c b/src/diff.c
index 7eafbdd..36cc76a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -378,21 +378,55 @@ main (int argc, char **argv)
         case 'D':
           specify_style (OUTPUT_IFDEF);
           {
-            static char const C_ifdef_group_formats[] =
-              "%%=%c#ifndef %s\n%%<#endif /* ! %s */\n%c#ifdef %s\n%%>#endif 
/* %s */\n%c#ifndef %s\n%%<#else /* %s */\n%%>#endif /* %s */\n";
-            char *b = xmalloc (sizeof C_ifdef_group_formats
-                               + 7 * strlen (optarg) - 14 /* 7*"%s" */
-                               - 8 /* 5*"%%" + 3*"%c" */);
-            sprintf (b, C_ifdef_group_formats,
-                     0,
-                     optarg, optarg, 0,
-                     optarg, optarg, 0,
-                     optarg, optarg, optarg);
-            for (i = 0; i < sizeof group_format / sizeof group_format[0]; i++)
-              {
-                specify_value (&group_format[i], b, "-D");
-                b += strlen (b) + 1;
-              }
+           static char const C_ifdef_group_formats[]
+             = (/* UNCHANGED */
+                "%="
+                "\0"
+
+                /* OLD */
+                "#ifndef @\n"
+                "%<"
+                "#endif /* ! @ */\n"
+                "\0"
+
+                /* NEW */
+                "#ifdef @\n"
+                "%>"
+                "#endif /* @ */\n"
+                "\0"
+
+                /* CHANGED */
+                "#ifndef @\n"
+                "%<"
+                "#else /* @ */\n"
+                "%>"
+                "#endif /* @ */\n");
+
+           char *b = xmalloc (sizeof C_ifdef_group_formats
+                              + 7 * strlen (optarg) - 7 /* 7*"@" */);
+           char *base = b;
+           int changes = 0;
+
+           for (i = 0; i < sizeof sizeof C_ifdef_group_formats; i++)
+             {
+               char ch = C_ifdef_group_formats[i];
+               switch (ch)
+                 {
+                 default:
+                   *b++ = ch;
+                   break;
+
+                 case '@':
+                   b = stpcpy (b, optarg);
+                   break;
+
+                 case '\0':
+                   *b++ = ch;
+                   specify_value (&group_format[changes++], base, "-D");
+                   base = b;
+                   break;
+                 }
+             }
           }
           break;
 
@@ -749,8 +783,12 @@ main (int argc, char **argv)
       if (!group_format[UNCHANGED])
         group_format[UNCHANGED] = "%=";
       if (!group_format[CHANGED])
-        group_format[CHANGED] = concat (group_format[OLD],
-                                        group_format[NEW], "");
+       {
+         char *p = xmalloc (strlen (group_format[OLD])
+                            + strlen (group_format[NEW]) + 1);
+         group_format[CHANGED] = p;
+         strcpy (stpcpy (p, group_format[OLD]), group_format[NEW]);
+       }
     }
 
   no_diff_means_no_output =
diff --git a/src/diff.h b/src/diff.h
index 227ca6a..03f00a6 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -382,9 +382,6 @@ extern void print_sdiff_script (struct change *);
 /* util.c */
 extern char const change_letter[4];
 extern char const pr_program[];
-extern char *concat (char const *, char const *, char const *)
-  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE
-  _GL_ATTRIBUTE_RETURNS_NONNULL;
 extern bool lines_differ (char const *, char const *) _GL_ATTRIBUTE_PURE;
 extern lin translate_line_number (struct file_data const *, lin);
 extern struct change *find_change (struct change *);
diff --git a/src/util.c b/src/util.c
index a8b2fb1..dd6d3bf 100644
--- a/src/util.c
+++ b/src/util.c
@@ -25,7 +25,6 @@
 #include <error.h>
 #include <system-quote.h>
 #include <xalloc.h>
-#include "xvasprintf.h"
 #include <signal.h>
 
 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
@@ -843,7 +842,14 @@ begin_output (void)
      of the pathnames, and it requires two spaces after "diff" if
      there are no options.  These requirements are silly and do not
      match historical practice.  */
-  name = xasprintf ("diff%s %s %s", switch_string, names[0], names[1]);
+  name = xmalloc (sizeof "diff" + strlen (switch_string)
+                 + 1 + strlen (names[0]) + 1 + strlen (names[1]));
+  char *p = stpcpy (name, "diff");
+  p = stpcpy (p, switch_string);
+  *p++ = ' ';
+  p = stpcpy (p, names[0]);
+  *p++ = ' ';
+  strcpy (p, names[1]);
 
   if (paginate)
     {
@@ -1536,16 +1542,6 @@ analyze_hunk (struct change *hunk,
   return (show_from ? OLD : UNCHANGED) | (show_to ? NEW : UNCHANGED);
 }
 
-/* Concatenate three strings, returning a newly malloc'd string.  */
-
-char *
-concat (char const *s1, char const *s2, char const *s3)
-{
-  char *new = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
-  sprintf (new, "%s%s%s", s1, s2, s3);
-  return new;
-}
-
 #ifdef DEBUG
 void
 debug_script (struct change *sp)
-- 
2.31.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]