[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
- [PATCH 03/17] diff3: suppress -fanalyzer alarms, (continued)
- [PATCH 03/17] diff3: suppress -fanalyzer alarms, Paul Eggert, 2021/08/22
- [PATCH 16/17] maint: refactor integer overflow checking, Paul Eggert, 2021/08/22
- [PATCH 04/17] maint: zalloc → xzalloc, Paul Eggert, 2021/08/22
- [PATCH 13/17] sdiff: fix unlikely memory leak, Paul Eggert, 2021/08/22
- [PATCH 02/17] maint: remove January workaround for Gnulib issue, Paul Eggert, 2021/08/22
- [PATCH 17/17] diff: add integer overflow checking, Paul Eggert, 2021/08/22
- [PATCH 10/17] maint: lint → GCC_LINT, Paul Eggert, 2021/08/22
- [PATCH 05/17] maint: remove prepargs, Paul Eggert, 2021/08/22
- [PATCH 07/17] maint: .gitignore updates, Paul Eggert, 2021/08/22
- [PATCH 11/17] maint: modernize IF_LINT for GCC 11.2.1, Paul Eggert, 2021/08/22
- [PATCH 15/17] diff: avoid sprintf %s,
Paul Eggert <=