diff: avoid sprintf %s

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.
This commit is contained in:
Paul Eggert 2021-08-22 13:54:04 -07:00
parent 31226b9bbe
commit dadc7f231f
4 changed files with 63 additions and 33 deletions

View File

@ -93,7 +93,6 @@ xmalloca
xreadlink
xstdopen
xstrtoimax
xvasprintf
'
# Additional xgettext options to use. Use "\\\newline" to break lines.

View File

@ -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 =

View File

@ -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 *);

View File

@ -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)