--- edit/editcmd.c.orig Thu Dec 19 19:01:34 2002
+++ edit/editcmd.c Tue Jun 15 03:16:08 2004
@@ -1546,51 +1546,56 @@
#define is_digit(x) ((x) >= '0' && (x) <= '9')
-#define snprintf(v) { \
+#define snprint(v) { \
*p1++ = *p++; \
- *p1++ = '%'; \
- *p1++ = 'n'; \
*p1 = '\0'; \
- sprintf(s,q1,v,&n); \
+ n = snprintf(s,e-s,q1,v); \
+ if (n >= e - s) goto nospc; \
s += n; \
}
/* this function uses the sprintf command to do a vprintf */
/* it takes pointers to arguments instead of the arguments themselves */
-static int sprintf_p (char *str, const char *fmt,...)
- __attribute__ ((format (printf, 2, 3)));
+/* The return value is the number of bytes written excluding '\0'
+ if successfull, -1 if the resulting string would be too long and
+ -2 if the format string is errorneous. */
+static int snprintf_p (char *str, size_t size, const char *fmt,...)
+ __attribute__ ((format (printf, 3, 4)));
-static int sprintf_p (char *str, const char *fmt,...)
+static int snprintf_p (char *str, size_t size, const char *fmt,...)
{
va_list ap;
- int n;
- char *q, *p, *s = str;
- char q1[32];
+ size_t n;
+ char *q, *p, *s = str, *e = str + size;
+ char q1[40];
char *p1;
+ int nargs = 0;
va_start (ap, fmt);
p = q = (char *) fmt;
while ((p = strchr (p, '%'))) {
n = p - q;
- strncpy (s, q, n); /* copy stuff between format specifiers */
+ if (n >= e - s)
+ goto nospc;
+ memcpy (s, q, n); /* copy stuff between format specifiers */
s += n;
- *s = 0;
q = p;
p1 = q1;
*p1++ = *p++;
if (*p == '%') {
p++;
*s++ = '%';
+ if (s == e)
+ goto nospc;
q = p;
continue;
}
- if (*p == 'n') {
- p++;
-/* do nothing */
- q = p;
- continue;
- }
+ if (*p == 'n')
+ goto err;
+ /* We were passed only 16 arguments. */
+ if (++nargs == 16)
+ goto err;
if (*p == '#')
*p1++ = *p++;
if (*p == '0')
@@ -1604,8 +1609,10 @@
strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */
p1 += strlen (p1);
} else {
- while (is_digit (*p))
+ while (is_digit (*p) && p1 < q1 + 20)
*p1++ = *p++;
+ if (is_digit (*p))
+ goto err;
}
if (*p == '.')
*p1++ = *p++;
@@ -1614,37 +1621,49 @@
strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */
p1 += strlen (p1);
} else {
- while (is_digit (*p))
+ while (is_digit (*p) && p1 < q1 + 32)
*p1++ = *p++;
+ if (is_digit (*p))
+ goto err;
}
/* flags done, now get argument */
if (*p == 's') {
- snprintf (va_arg (ap, char *));
+ snprint (va_arg (ap, char *));
} else if (*p == 'h') {
if (strchr ("diouxX", *p))
- snprintf (*va_arg (ap, short *));
+ snprint (*va_arg (ap, short *));
} else if (*p == 'l') {
*p1++ = *p++;
if (strchr ("diouxX", *p))
- snprintf (*va_arg (ap, long *));
+ snprint (*va_arg (ap, long *));
} else if (strchr ("cdiouxX", *p)) {
- snprintf (*va_arg (ap, int *));
+ snprint (*va_arg (ap, int *));
} else if (*p == 'L') {
*p1++ = *p++;
if (strchr ("EefgG", *p))
- snprintf (*va_arg (ap, double *)); /* should be long double */
+ snprint (*va_arg (ap, double *)); /* should be long double */
} else if (strchr ("EefgG", *p)) {
- snprintf (*va_arg (ap, double *));
+ snprint (*va_arg (ap, double *));
} else if (strchr ("DOU", *p)) {
- snprintf (*va_arg (ap, long *));
+ snprint (*va_arg (ap, long *));
} else if (*p == 'p') {
- snprintf (*va_arg (ap, void **));
- }
+ snprint (*va_arg (ap, void **));
+ } else
+ goto err;
q = p;
}
va_end (ap);
- sprintf (s, q); /* print trailing leftover */
- return s - str + strlen (s);
+ n = strlen (q);
+ if (n >= e - s)
+ return -1;
+ memcpy (s, q, n + 1);
+ return s + n - str;
+nospc:
+ va_end (ap);
+ return -1;
+err:
+ va_end (ap);
+ return -2;
}
static void regexp_error (WEdit *edit)
@@ -1737,7 +1756,7 @@
for (i = 0; i < NUM_REPL_ARGS; i++) {
if (s != (char *) 1 && *s) {
ord = atoi (s);
- if ((ord > 0) && (ord < NUM_REPL_ARGS))
+ if ((ord > 0) && (ord <= NUM_REPL_ARGS))
argord[i] = ord - 1;
else
argord[i] = i;
@@ -1821,6 +1840,7 @@
if (replace_yes) { /* delete then insert new */
if (replace_scanf || replace_regexp) {
char repl_str[MAX_REPL_LEN + 2];
+ int ret = 0;
/* we need to fill in sargs just like with scanf */
if (replace_regexp) {
@@ -1829,6 +1849,11 @@
k < NUM_REPL_ARGS && pmatch[k].rm_eo >= 0;
k++) {
unsigned char *t;
+
+ if (pmatch[k].rm_eo - pmatch[k].rm_so > 255) {
+ ret = -1;
+ break;
+ }
t = (unsigned char *) &sargs[k - 1][0];
for (j = 0;
j < pmatch[k].rm_eo - pmatch[k].rm_so
@@ -1849,7 +1874,9 @@
for (; k <= NUM_REPL_ARGS; k++)
sargs[k - 1][0] = 0;
}
- if (sprintf_p (repl_str, exp2, PRINTF_ARGS) >= 0) {
+ if (!ret)
+ ret = snprintf_p (repl_str, MAX_REPL_LEN + 2, exp2, PRINTF_ARGS);
+ if (ret >= 0) {
times_replaced++;
while (i--)
edit_delete (edit);
@@ -1857,8 +1884,9 @@
edit_insert (edit, repl_str[i]);
} else {
edit_error_dialog (_(" Replace "),
- _
- (" Error in replacement format string. "));
+ ret == -2
+ ? _(" Error in replacement format string. ")
+ : _(" Replacement too long. "));
replace_continue = 0;
}
} else {
@@ -2711,7 +2739,7 @@
int word_len = 0, i, num_compl = 0, max_len;
long word_start = 0;
char *bufpos;
- char match_expr[MAX_REPL_LEN];
+ char *match_expr;
struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
/* don't want to disturb another search */
@@ -2728,9 +2756,7 @@
/* prepare match expression */
bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE]
[word_start & M_EDIT_BUF_SIZE];
- strncpy (match_expr, bufpos, word_len);
- match_expr[word_len] = '\0';
- strcat (match_expr, "[a-zA-Z_0-9]+");
+ match_expr = g_strdup_printf ("%.*s[a-zA-Z_0-9]+", word_len, bufpos);
/* init search: backward, regexp, whole word, case sensitive */
edit_set_search_parameters (0, 1, 1, 1, 1);
@@ -2762,6 +2788,8 @@
}
/* release memory before return */
+ g_free (match_expr);
+
for (i = 0; i < num_compl; i++)
g_free (compl[i].text);