summaryrefslogtreecommitdiff
path: root/lib-src/etags.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2019-11-26 13:53:41 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2019-11-26 13:57:00 -0800
commitcffa5703b95fba3624dc54db5e693bae559eac5f (patch)
tree7ac0719a3db6a29399ed4389ff27f1d0aeb211e5 /lib-src/etags.c
parent75b41a38dd0735fe63457e12741656c63972d3ce (diff)
downloademacs-cffa5703b95fba3624dc54db5e693bae559eac5f.tar.gz
etags: remove some arbitrary limits
etags had undefined behavior if input files, lines, tags, etc., had more than INT_MAX bytes. Clean up the usage of integer types to fix the overflow errors I found. * admin/merge-gnulib (GNULIB_MODULES): Add mempcpy. * lib-src/etags.c: Include inttypes.h, intprops.h. (memcpyz): New function. Use it to simplify several occurrences of memcpy followed by storing a trailing '\0'. (xnew): Use xnmalloc, to catch overflow on integer multiplication. (xrnew): Change last arg to multiplier. The type is not needed. All callers changed. (node, lineno, charno, linecharno, invalidcharno, make_tag): (pfnote, add_node, number_len, C_symtype, lbz, Makefile_targets) (readline): Use intmax_t for line numbers and character positions, instead of int or long. (linebuffer, make_tag, pfnote, total_size_of_entries, put_entry) (in_word_set, C_symtype, token, cstack, pushclass_above): (popclass_above, write_classname, consider_token, C_entries) (Ruby_functions, Makefile_targets, Lua_functions, TeX_commands) (TeX_decode_env, erlang_func, erlang_attribute, erlang_atom) (substitute, regex_tag_multiline, nocase_tail, readline_interval) (readline, savenstr, concat, etags_getcwd, relative_filename) (linebuffer_setlen): Use ptrdiff_t for object sizes, instead of int or long or unsigned or size_t. (write_classname, C_entries): Avoid sprintf, as the result could exceed INT_MAX bytes and then behavior goes haywire. (main): Use int, instead of unsigned, for argv counts. (get_language_from_filename): Use bool for boolean. (Ruby_functions): Prefer strcpy to memcpy when copying "=". (linebuffer_setlen): Use ‘if’ instead of ‘while’. (memory_full, xnmalloc, xnrealloc): New functions. (xmalloc): Use memory_full, and take a ptrdiff_t instead of a size_t. (xrealloc): Remove; no longer needed. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/mempcpy.c, m4/mempcpy.m4: New files, copied from Gnulib.
Diffstat (limited to 'lib-src/etags.c')
-rw-r--r--lib-src/etags.c404
1 files changed, 211 insertions, 193 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 6409407e466..0665cb00b9b 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -114,6 +114,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
# define O_CLOEXEC O_NOINHERIT
#endif /* WINDOWSNT */
+#include <inttypes.h>
#include <limits.h>
#include <unistd.h>
#include <stdarg.h>
@@ -123,6 +124,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
#include <errno.h>
#include <fcntl.h>
#include <binary-io.h>
+#include <intprops.h>
#include <unlocked-io.h>
#include <c-ctype.h>
#include <c-strcase.h>
@@ -141,6 +143,14 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
# define CTAGS false
#endif
+/* Copy to DEST from SRC (containing LEN bytes), and append a NUL byte. */
+static void
+memcpyz (void *dest, void const *src, ptrdiff_t len)
+{
+ char *e = mempcpy (dest, src, len);
+ *e = '\0';
+}
+
static bool
streq (char const *s, char const *t)
{
@@ -235,11 +245,11 @@ endtoken (unsigned char c)
/*
* xnew, xrnew -- allocate, reallocate storage
*
- * SYNOPSIS: Type *xnew (int n, Type);
- * void xrnew (OldPointer, int n, Type);
+ * SYNOPSIS: Type *xnew (ptrdiff_t n, Type);
+ * void xrnew (OldPointer, ptrdiff_t n, int multiplier);
*/
-#define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type)))
-#define xrnew(op, n, Type) ((op) = (Type *) xrealloc (op, (n) * sizeof (Type)))
+#define xnew(n, Type) ((Type *) xnmalloc (n, sizeof (Type)))
+#define xrnew(op, n, m) ((op) = xnrealloc (op, n, (m) * sizeof *(op)))
typedef void Lang_function (FILE *);
@@ -282,8 +292,8 @@ typedef struct node_st
bool valid; /* write this tag on the tag file */
bool is_func; /* function tag: use regexp in CTAGS mode */
bool been_warned; /* warning already given for duplicated tag */
- int lno; /* line number tag is on */
- long cno; /* character number line starts on */
+ intmax_t lno; /* line number tag is on */
+ intmax_t cno; /* character number line starts on */
} node;
/*
@@ -295,8 +305,8 @@ typedef struct node_st
*/
typedef struct
{
- long size;
- int len;
+ ptrdiff_t size;
+ ptrdiff_t len;
char *buffer;
} linebuffer;
@@ -365,7 +375,7 @@ static void just_read_file (FILE *);
static language *get_language_from_langname (const char *);
static void readline (linebuffer *, FILE *);
-static long readline_internal (linebuffer *, FILE *, char const *);
+static ptrdiff_t readline_internal (linebuffer *, FILE *, char const *);
static bool nocase_tail (const char *);
static void get_tag (char *, char **);
static void get_lispy_tag (char *);
@@ -385,7 +395,7 @@ static void process_file (FILE *, char *, language *);
static void find_entries (FILE *);
static void free_tree (node *);
static void free_fdesc (fdesc *);
-static void pfnote (char *, bool, char *, int, int, long);
+static void pfnote (char *, bool, char *, ptrdiff_t, intmax_t, intmax_t);
static void invalidate_nodes (fdesc *, node **);
static void put_entries (node *);
@@ -393,7 +403,7 @@ static char *concat (const char *, const char *, const char *);
static char *skip_spaces (char *);
static char *skip_non_spaces (char *);
static char *skip_name (char *);
-static char *savenstr (const char *, int);
+static char *savenstr (const char *, ptrdiff_t);
static char *savestr (const char *);
static char *etags_getcwd (void);
static char *relative_filename (char *, char *);
@@ -403,9 +413,11 @@ static bool filename_is_absolute (char *f);
static void canonicalize_filename (char *);
static char *etags_mktmp (void);
static void linebuffer_init (linebuffer *);
-static void linebuffer_setlen (linebuffer *, int);
-static void *xmalloc (size_t);
-static void *xrealloc (void *, size_t);
+static void linebuffer_setlen (linebuffer *, ptrdiff_t);
+static void *xmalloc (ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1));
+static void *xnmalloc (ptrdiff_t, ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1,2));
+static void *xnrealloc (void *, ptrdiff_t, ptrdiff_t)
+ ATTRIBUTE_ALLOC_SIZE ((2,3));
static char searchar = '/'; /* use /.../ searches */
@@ -420,12 +432,12 @@ static ptrdiff_t whatlen_max; /* maximum length of any 'what' member */
static fdesc *fdhead; /* head of file description list */
static fdesc *curfdp; /* current file description */
static char *infilename; /* current input file name */
-static int lineno; /* line number of current line */
-static long charno; /* current character number */
-static long linecharno; /* charno of start of current line */
+static intmax_t lineno; /* line number of current line */
+static intmax_t charno; /* current character number */
+static intmax_t linecharno; /* charno of start of current line */
static char *dbp; /* pointer to start of current tag */
-static const int invalidcharno = -1;
+static intmax_t const invalidcharno = -1;
static node *nodehead; /* the head of the binary tree of tags */
static node *last_node; /* the last node created */
@@ -1070,7 +1082,7 @@ int
main (int argc, char **argv)
{
int i;
- unsigned int nincluded_files;
+ int nincluded_files;
char **included_files;
argument *argbuffer;
int current_arg, file_count;
@@ -1484,7 +1496,7 @@ get_language_from_interpreter (char *interpreter)
* Return a language given the file name.
*/
static language *
-get_language_from_filename (char *file, int case_sensitive)
+get_language_from_filename (char *file, bool case_sensitive)
{
language *lang;
const char **name, **ext, *suffix;
@@ -1918,26 +1930,26 @@ find_entries (FILE *inf)
*/
static void
make_tag (const char *name, /* tag name, or NULL if unnamed */
- int namelen, /* tag length */
+ ptrdiff_t namelen, /* tag length */
bool is_func, /* tag is a function */
char *linestart, /* start of the line where tag is */
- int linelen, /* length of the line where tag is */
- int lno, /* line number */
- long int cno) /* character number */
+ ptrdiff_t linelen, /* length of the line where tag is */
+ intmax_t lno, /* line number */
+ intmax_t cno) /* character number */
{
bool named = (name != NULL && namelen > 0);
char *nname = NULL;
if (debug)
- fprintf (stderr, "%s on %s:%d: %s\n",
+ fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n",
named ? name : "(unnamed)", curfdp->taggedfname, lno, linestart);
if (!CTAGS && named) /* maybe set named to false */
/* Let's try to make an implicit tag name, that is, create an unnamed tag
such that etags.el can guess a name from it. */
{
- int i;
- register const char *cp = name;
+ ptrdiff_t i;
+ const char *cp = name;
for (i = 0; i < namelen; i++)
if (notinname (*cp++))
@@ -1963,8 +1975,8 @@ make_tag (const char *name, /* tag name, or NULL if unnamed */
/* Record a tag. */
static void
-pfnote (char *name, bool is_func, char *linestart, int linelen, int lno,
- long int cno)
+pfnote (char *name, bool is_func, char *linestart, ptrdiff_t linelen,
+ intmax_t lno, intmax_t cno)
/* tag name, or NULL if unnamed */
/* tag is a function */
/* start of the line where tag is */
@@ -2197,7 +2209,8 @@ add_node (node *np, node **cur_node_p)
if (!no_warnings)
{
fprintf (stderr,
- "Duplicate entry in file %s, line %d: %s\n",
+ ("Duplicate entry in file %s, "
+ "line %"PRIdMAX": %s\n"),
np->fdp->infname, lineno, np->name);
fprintf (stderr, "Second entry ignored\n");
}
@@ -2293,12 +2306,12 @@ invalidate_nodes (fdesc *badfdp, node **npp)
}
-static int total_size_of_entries (node *);
-static int number_len (long) ATTRIBUTE_CONST;
+static ptrdiff_t total_size_of_entries (node *);
+static int number_len (intmax_t) ATTRIBUTE_CONST;
/* Length of a non-negative number's decimal representation. */
static int
-number_len (long int num)
+number_len (intmax_t num)
{
int len = 1;
while ((num /= 10) > 0)
@@ -2312,10 +2325,10 @@ number_len (long int num)
* This count is irrelevant with etags.el since emacs 19.34 at least,
* but is still supplied for backward compatibility.
*/
-static int
-total_size_of_entries (register node *np)
+static ptrdiff_t
+total_size_of_entries (node *np)
{
- register int total = 0;
+ ptrdiff_t total = 0;
for (; np != NULL; np = np->right)
if (np->valid)
@@ -2323,7 +2336,7 @@ total_size_of_entries (register node *np)
total += strlen (np->regex) + 1; /* pat\177 */
if (np->name != NULL)
total += strlen (np->name) + 1; /* name\001 */
- total += number_len ((long) np->lno) + 1; /* lno, */
+ total += number_len (np->lno) + 1; /* lno, */
if (np->cno != invalidcharno) /* cno */
total += number_len (np->cno);
total += 1; /* newline */
@@ -2347,7 +2360,7 @@ put_entry (node *np)
if (fdp != np->fdp)
{
fdp = np->fdp;
- fprintf (tagf, "\f\n%s,%d\n",
+ fprintf (tagf, "\f\n%s,%"PRIdPTR"\n",
fdp->taggedfname, total_size_of_entries (np));
fdp->written = true;
}
@@ -2358,9 +2371,9 @@ put_entry (node *np)
fputs (np->name, tagf);
fputc ('\001', tagf);
}
- fprintf (tagf, "%d,", np->lno);
+ fprintf (tagf, "%"PRIdMAX",", np->lno);
if (np->cno != invalidcharno)
- fprintf (tagf, "%ld", np->cno);
+ fprintf (tagf, "%"PRIdMAX, np->cno);
fputs ("\n", tagf);
}
else
@@ -2372,10 +2385,10 @@ put_entry (node *np)
if (cxref_style)
{
if (vgrind_style)
- fprintf (stdout, "%s %s %d\n",
+ fprintf (stdout, "%s %s %"PRIdMAX"\n",
np->name, np->fdp->taggedfname, (np->lno + 63) / 64);
else
- fprintf (stdout, "%-16s %3d %-16s %s\n",
+ fprintf (stdout, "%-16s %3"PRIdMAX" %-16s %s\n",
np->name, np->lno, np->fdp->taggedfname, np->regex);
}
else
@@ -2397,7 +2410,7 @@ put_entry (node *np)
}
else
{ /* anything else; text pattern inadequate */
- fprintf (tagf, "%d", np->lno);
+ fprintf (tagf, "%"PRIdMAX, np->lno);
}
putc ('\n', tagf);
}
@@ -2591,7 +2604,7 @@ hash (const char *str, int len)
}
static struct C_stab_entry *
-in_word_set (register const char *str, register unsigned int len)
+in_word_set (const char *str, ptrdiff_t len)
{
enum
{
@@ -2658,9 +2671,9 @@ in_word_set (register const char *str, register unsigned int len)
/*%>*/
static enum sym_type
-C_symtype (char *str, int len, int c_ext)
+C_symtype (char *str, ptrdiff_t len, int c_ext)
{
- register struct C_stab_entry *se = in_word_set (str, len);
+ struct C_stab_entry *se = in_word_set (str, len);
if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
return st_none;
@@ -2770,8 +2783,8 @@ static enum
static struct tok
{
char *line; /* string containing the token */
- int offset; /* where the token starts in LINE */
- int length; /* token length */
+ ptrdiff_t offset; /* where the token starts in LINE */
+ ptrdiff_t length; /* token length */
/*
The previous members can be used to pass strings around for generic
purposes. The following ones specifically refer to creating tags. In this
@@ -2782,23 +2795,23 @@ static struct tok
invalidated whenever a state machine is
reset prematurely */
bool named; /* create a named tag */
- int lineno; /* source line number of tag */
- long linepos; /* source char number of tag */
+ intmax_t lineno; /* source line number of tag */
+ intmax_t linepos; /* source char number of tag */
} token; /* latest token read */
/*
* Variables and functions for dealing with nested structures.
* Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
*/
-static void pushclass_above (int, char *, int);
-static void popclass_above (int);
+static void pushclass_above (ptrdiff_t, char *, ptrdiff_t);
+static void popclass_above (ptrdiff_t);
static void write_classname (linebuffer *, const char *qualifier);
static struct {
char **cname; /* nested class names */
- int *bracelev; /* nested class brace level */
- int nl; /* class nesting level (elements used) */
- int size; /* length of the array */
+ ptrdiff_t *bracelev; /* nested class brace level */
+ ptrdiff_t nl; /* class nesting level (elements used) */
+ ptrdiff_t size; /* length of the array */
} cstack; /* stack for nested declaration tags */
/* Current struct nesting depth (namespace, class, struct, union, enum). */
#define nestlev (cstack.nl)
@@ -2807,17 +2820,17 @@ static struct {
&& bracelev == cstack.bracelev[nestlev-1] + 1)
static void
-pushclass_above (int bracelev, char *str, int len)
+pushclass_above (ptrdiff_t bracelev, char *str, ptrdiff_t len)
{
- int nl;
+ ptrdiff_t nl;
popclass_above (bracelev);
nl = cstack.nl;
if (nl >= cstack.size)
{
- int size = cstack.size *= 2;
- xrnew (cstack.cname, size, char *);
- xrnew (cstack.bracelev, size, int);
+ xrnew (cstack.cname, cstack.size, 2);
+ xrnew (cstack.bracelev, cstack.size, 2);
+ cstack.size *= 2;
}
assert (nl == 0 || cstack.bracelev[nl-1] < bracelev);
cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len);
@@ -2826,11 +2839,9 @@ pushclass_above (int bracelev, char *str, int len)
}
static void
-popclass_above (int bracelev)
+popclass_above (ptrdiff_t bracelev)
{
- int nl;
-
- for (nl = cstack.nl - 1;
+ for (ptrdiff_t nl = cstack.nl - 1;
nl >= 0 && cstack.bracelev[nl] >= bracelev;
nl--)
{
@@ -2842,8 +2853,7 @@ popclass_above (int bracelev)
static void
write_classname (linebuffer *cn, const char *qualifier)
{
- int i, len;
- int qlen = strlen (qualifier);
+ ptrdiff_t len;
if (cstack.nl == 0 || cstack.cname[0] == NULL)
{
@@ -2857,18 +2867,22 @@ write_classname (linebuffer *cn, const char *qualifier)
linebuffer_setlen (cn, len);
strcpy (cn->buffer, cstack.cname[0]);
}
- for (i = 1; i < cstack.nl; i++)
+ for (ptrdiff_t i = 1; i < cstack.nl; i++)
{
char *s = cstack.cname[i];
if (s == NULL)
continue;
- linebuffer_setlen (cn, len + qlen + strlen (s));
- len += sprintf (cn->buffer + len, "%s%s", qualifier, s);
+ int qlen = strlen (qualifier);
+ ptrdiff_t slen = strlen (s);
+ linebuffer_setlen (cn, len + qlen + slen);
+ memcpyz (stpcpy (cn->buffer + len, qualifier), s, slen);
+ len += qlen + slen;
}
}
-static bool consider_token (char *, int, int, int *, int, int, bool *);
+static bool consider_token (char *, ptrdiff_t, int, int *,
+ ptrdiff_t, ptrdiff_t, bool *);
static void make_C_tag (bool);
/*
@@ -2889,8 +2903,8 @@ static void make_C_tag (bool);
*/
static bool
-consider_token (char *str, int len, int c, int *c_extp,
- int bracelev, int parlev, bool *is_func_or_var)
+consider_token (char *str, ptrdiff_t len, int c, int *c_extp,
+ ptrdiff_t bracelev, ptrdiff_t parlev, bool *is_func_or_var)
/* IN: token pointer */
/* IN: token length */
/* IN: first char after the token */
@@ -2903,7 +2917,7 @@ consider_token (char *str, int len, int c, int *c_extp,
structtype is the type of the preceding struct-like keyword, and
structbracelev is the brace level where it has been seen. */
static enum sym_type structtype;
- static int structbracelev;
+ static ptrdiff_t structbracelev;
static enum sym_type toktype;
@@ -3098,8 +3112,7 @@ consider_token (char *str, int len, int c, int *c_extp,
fvdef = fvnone;
objdef = omethodtag;
linebuffer_setlen (&token_name, len);
- memcpy (token_name.buffer, str, len);
- token_name.buffer[len] = '\0';
+ memcpyz (token_name.buffer, str, len);
return true;
}
return false;
@@ -3113,11 +3126,10 @@ consider_token (char *str, int len, int c, int *c_extp,
objdef = omethodtag;
if (class_qualify)
{
- int oldlen = token_name.len;
+ ptrdiff_t oldlen = token_name.len;
fvdef = fvnone;
linebuffer_setlen (&token_name, oldlen + len);
- memcpy (token_name.buffer + oldlen, str, len);
- token_name.buffer[oldlen + len] = '\0';
+ memcpyz (token_name.buffer + oldlen, str, len);
}
return true;
}
@@ -3228,7 +3240,7 @@ consider_token (char *str, int len, int c, int *c_extp,
*/
static struct
{
- long linepos;
+ intmax_t linepos;
linebuffer lb;
} lbs[2];
@@ -3302,19 +3314,19 @@ C_entries (int c_ext, FILE *inf)
/* extension of C */
/* input file */
{
- register char c; /* latest char read; '\0' for end of line */
- register char *lp; /* pointer one beyond the character `c' */
- int curndx, newndx; /* indices for current and new lb */
- register int tokoff; /* offset in line of start of current token */
- register int toklen; /* length of current token */
+ char c; /* latest char read; '\0' for end of line */
+ char *lp; /* pointer one beyond the character `c' */
+ bool curndx, newndx; /* indices for current and new lb */
+ ptrdiff_t tokoff; /* offset in line of start of current token */
+ ptrdiff_t toklen; /* length of current token */
const char *qualifier; /* string used to qualify names */
int qlen; /* length of qualifier */
- int bracelev; /* current brace level */
- int bracketlev; /* current bracket level */
- int parlev; /* current parenthesis level */
- int attrparlev; /* __attribute__ parenthesis level */
- int templatelev; /* current template level */
- int typdefbracelev; /* bracelev where a typedef struct body begun */
+ ptrdiff_t bracelev; /* current brace level */
+ ptrdiff_t bracketlev; /* current bracket level */
+ ptrdiff_t parlev; /* current parenthesis level */
+ ptrdiff_t attrparlev; /* __attribute__ parenthesis level */
+ ptrdiff_t templatelev; /* current template level */
+ ptrdiff_t typdefbracelev; /* bracelev where a typedef struct body begun */
bool incomm, inquote, inchar, quotednl, midtoken;
bool yacc_rules; /* in the rules part of a yacc file */
struct tok savetoken = {0}; /* token saved during preprocessor handling */
@@ -3327,7 +3339,7 @@ C_entries (int c_ext, FILE *inf)
cstack.size = (DEBUG) ? 1 : 4;
cstack.nl = 0;
cstack.cname = xnew (cstack.size, char *);
- cstack.bracelev = xnew (cstack.size, int);
+ cstack.bracelev = xnew (cstack.size, ptrdiff_t);
}
tokoff = toklen = typdefbracelev = 0; /* keep compiler quiet */
@@ -3579,20 +3591,19 @@ C_entries (int c_ext, FILE *inf)
{
if (class_qualify)
{
- int len;
write_classname (&token_name, qualifier);
- len = token_name.len;
+ ptrdiff_t len = token_name.len;
linebuffer_setlen (&token_name,
len + qlen + toklen);
- sprintf (token_name.buffer + len, "%s%.*s",
- qualifier, toklen,
- newlb.buffer + tokoff);
+ memcpyz (stpcpy (token_name.buffer + len,
+ qualifier),
+ newlb.buffer + tokoff, toklen);
}
else
{
linebuffer_setlen (&token_name, toklen);
- sprintf (token_name.buffer, "%.*s",
- toklen, newlb.buffer + tokoff);
+ memcpyz (token_name.buffer,
+ newlb.buffer + tokoff, toklen);
}
token.named = true;
}
@@ -3601,17 +3612,19 @@ C_entries (int c_ext, FILE *inf)
{
if (class_qualify)
{
- int len = strlen (objtag) + 2 + toklen;
+ ptrdiff_t len = strlen (objtag) + 2 + toklen;
linebuffer_setlen (&token_name, len);
- sprintf (token_name.buffer, "%s(%.*s)",
- objtag, toklen,
- newlb.buffer + tokoff);
+ char *p1 = stpcpy (token_name.buffer, objtag);
+ char *p2 = stpcpy (p1, "(");
+ char *p3 = mempcpy (p2, newlb.buffer + tokoff,
+ toklen);
+ strcpy (p3, ")");
}
else
{
linebuffer_setlen (&token_name, toklen);
- sprintf (token_name.buffer, "%.*s",
- toklen, newlb.buffer + tokoff);
+ memcpyz (token_name.buffer,
+ newlb.buffer + tokoff, toklen);
}
token.named = true;
}
@@ -3625,8 +3638,8 @@ C_entries (int c_ext, FILE *inf)
/* GNU DEFUN and similar macros */
{
bool defun = (newlb.buffer[tokoff] == 'F');
- int off = tokoff;
- int len = toklen;
+ ptrdiff_t off = tokoff;
+ ptrdiff_t len = toklen;
if (defun)
{
@@ -3635,9 +3648,8 @@ C_entries (int c_ext, FILE *inf)
/* First, tag it as its C name */
linebuffer_setlen (&token_name, toklen);
- memcpy (token_name.buffer,
- newlb.buffer + tokoff, toklen);
- token_name.buffer[toklen] = '\0';
+ memcpyz (token_name.buffer,
+ newlb.buffer + tokoff, toklen);
token.named = true;
token.lineno = lineno;
token.offset = tokoff;
@@ -3650,9 +3662,8 @@ C_entries (int c_ext, FILE *inf)
/* Rewrite the tag so that emacs lisp DEFUNs
can be found also by their elisp name */
linebuffer_setlen (&token_name, len);
- memcpy (token_name.buffer,
- newlb.buffer + off, len);
- token_name.buffer[len] = '\0';
+ memcpyz (token_name.buffer,
+ newlb.buffer + off, len);
if (defun)
while (--len >= 0)
if (token_name.buffer[len] == '_')
@@ -3662,9 +3673,8 @@ C_entries (int c_ext, FILE *inf)
else
{
linebuffer_setlen (&token_name, toklen);
- memcpy (token_name.buffer,
- newlb.buffer + tokoff, toklen);
- token_name.buffer[toklen] = '\0';
+ memcpyz (token_name.buffer,
+ newlb.buffer + tokoff, toklen);
/* Name macros and members. */
token.named = (structdef == stagseen
|| typdef == ttypeseen
@@ -3790,7 +3800,7 @@ C_entries (int c_ext, FILE *inf)
objdef = omethodcolon;
if (class_qualify)
{
- int toklen = token_name.len;
+ ptrdiff_t toklen = token_name.len;
linebuffer_setlen (&token_name, toklen + 1);
strcpy (token_name.buffer + toklen, ":");
}
@@ -4061,7 +4071,7 @@ C_entries (int c_ext, FILE *inf)
}
if (uqname > token_name.buffer)
{
- int uqlen = strlen (uqname);
+ ptrdiff_t uqlen = strlen (uqname);
linebuffer_setlen (&token_name, uqlen);
memmove (token_name.buffer, uqname, uqlen + 1);
}
@@ -4979,12 +4989,11 @@ Ruby_functions (FILE *inf)
size_t name_len = cp - np + 1;
char *wr_name = xnew (name_len + 1, char);
- memcpy (wr_name, np, name_len - 1);
- memcpy (wr_name + name_len - 1, "=", 2);
+ strcpy (mempcpy (wr_name, np, name_len - 1), "=");
pfnote (wr_name, true, lb.buffer, cp - lb.buffer + 1,
lineno, linecharno);
if (debug)
- fprintf (stderr, "%s on %s:%d: %s\n", wr_name,
+ fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n", wr_name,
curfdp->taggedfname, lineno, lb.buffer);
continuation = false;
}
@@ -5178,8 +5187,8 @@ static void
Pascal_functions (FILE *inf)
{
linebuffer tline; /* mostly copied from C_entries */
- long save_lcno;
- int save_lineno, namelen, taglen;
+ intmax_t save_lcno, save_lineno;
+ ptrdiff_t namelen, taglen;
char c, *name;
bool /* each of these flags is true if: */
@@ -5455,7 +5464,7 @@ Lua_functions (FILE *inf)
if (tp_dot || tp_colon)
{
char *p = tp_dot > tp_colon ? tp_dot : tp_colon;
- int len_add = p - tag_name + 1;
+ ptrdiff_t len_add = p - tag_name + 1;
get_tag (bp + len_add, NULL);
}
@@ -5656,7 +5665,7 @@ TeX_commands (FILE *inf)
if (strneq (cp, key->buffer, key->len))
{
char *p;
- int namelen, linelen;
+ ptrdiff_t namelen, linelen;
bool opgrp = false;
cp = skip_spaces (cp + key->len);
@@ -5693,8 +5702,8 @@ TeX_commands (FILE *inf)
static void
TEX_decode_env (const char *evarname, const char *defenv)
{
- register const char *env, *p;
- int i, len;
+ const char *env, *p;
+ ptrdiff_t len;
/* Append default string to environment. */
env = getenv (evarname);
@@ -5711,7 +5720,7 @@ TEX_decode_env (const char *evarname, const char *defenv)
/* Unpack environment string into token table. Be careful about */
/* zero-length strings (leading ':', "::" and trailing ':') */
- for (i = 0; *env != '\0';)
+ for (ptrdiff_t i = 0; *env != '\0'; )
{
p = strchr (env, ':');
if (!p) /* End of environment string. */
@@ -5811,8 +5820,7 @@ HTML_labels (FILE *inf)
for (end = dbp; *end != '\0' && intoken (*end); end++)
continue;
linebuffer_setlen (&token_name, end - dbp);
- memcpy (token_name.buffer, dbp, end - dbp);
- token_name.buffer[end - dbp] = '\0';
+ memcpyz (token_name.buffer, dbp, end - dbp);
dbp = end;
intag = false; /* we found what we looked for */
@@ -5906,11 +5914,10 @@ Prolog_functions (FILE *inf)
tags later. */
if (allocated <= len)
{
- xrnew (last, len + 1, char);
+ xrnew (last, len + 1, 1);
allocated = len + 1;
}
- memcpy (last, cp, len);
- last[len] = '\0';
+ memcpyz (last, cp, len);
lastlen = len;
}
}
@@ -6031,9 +6038,9 @@ prolog_atom (char *s, size_t pos)
* Assumes that Erlang functions start at column 0.
* Original code by Anders Lindgren (1996)
*/
-static int erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *);
+static ptrdiff_t erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *);
static void erlang_attribute (char *);
-static int erlang_atom (char *);
+static ptrdiff_t erlang_atom (char *);
static void
Erlang_functions (FILE *inf)
@@ -6070,11 +6077,10 @@ Erlang_functions (FILE *inf)
tags later. */
if (allocated <= len)
{
- xrnew (last, len + 1, char);
+ xrnew (last, len + 1, 1);
allocated = len + 1;
}
- memcpy (last, cp + name_offset, len);
- last[len] = '\0';
+ memcpyz (last, cp + name_offset, len);
lastlen = len;
}
}
@@ -6093,7 +6099,7 @@ Erlang_functions (FILE *inf)
* Return the size of the name of the function, or 0 if no function
* was found.
*/
-static int
+static ptrdiff_t
erlang_func (char *s, char *last, ptrdiff_t lastlen, ptrdiff_t *name_offset)
{
char *name = s;
@@ -6133,15 +6139,13 @@ static void
erlang_attribute (char *s)
{
char *cp = s;
- int pos;
- int len;
if ((LOOKING_AT (cp, "-define") || LOOKING_AT (cp, "-record"))
&& *cp++ == '(')
{
cp = skip_spaces (cp);
- len = erlang_atom (cp);
- pos = cp + len - s;
+ ptrdiff_t len = erlang_atom (cp);
+ ptrdiff_t pos = cp + len - s;
if (len > 0)
{
/* If the name is quoted, the quotes are not part of the name. */
@@ -6161,10 +6165,10 @@ erlang_attribute (char *s)
* Consume an Erlang atom (or variable).
* Return the number of bytes consumed, or -1 if there was an error.
*/
-static int
+static ptrdiff_t
erlang_atom (char *s)
{
- int pos = 0;
+ ptrdiff_t pos = 0;
if (c_isalpha (s[pos]) || s[pos] == '_')
{
@@ -6437,10 +6441,9 @@ static char *
substitute (char *in, char *out, struct re_registers *regs)
{
char *result, *t;
- int size, dig, diglen;
result = NULL;
- size = strlen (out);
+ ptrdiff_t size = strlen (out);
/* Pass 1: figure out how much to allocate by finding all \N strings. */
if (out[size - 1] == '\\')
@@ -6450,8 +6453,8 @@ substitute (char *in, char *out, struct re_registers *regs)
t = strchr (t + 2, '\\'))
if (c_isdigit (t[1]))
{
- dig = t[1] - '0';
- diglen = regs->end[dig] - regs->start[dig];
+ int dig = t[1] - '0';
+ ptrdiff_t diglen = regs->end[dig] - regs->start[dig];
size += diglen - 2;
}
else
@@ -6464,8 +6467,8 @@ substitute (char *in, char *out, struct re_registers *regs)
for (t = result; *out != '\0'; out++)
if (*out == '\\' && c_isdigit (*++out))
{
- dig = *out - '0';
- diglen = regs->end[dig] - regs->start[dig];
+ int dig = *out - '0';
+ ptrdiff_t diglen = regs->end[dig] - regs->start[dig];
memcpy (t, in + regs->start[dig], diglen);
t += diglen;
}
@@ -6474,7 +6477,7 @@ substitute (char *in, char *out, struct re_registers *regs)
*t = '\0';
assert (t <= result + size);
- assert (t - result == (int)strlen (result));
+ assert (t == result + strlen (result));
return result;
}
@@ -6511,7 +6514,7 @@ regex_tag_multiline (void)
for (rp = p_head; rp != NULL; rp = rp->p_next)
{
- int match = 0;
+ ptrdiff_t match = 0;
if (!rp->multi_line)
continue; /* skip normal regexps */
@@ -6572,7 +6575,7 @@ regex_tag_multiline (void)
charno - linecharno + 1, lineno, linecharno);
if (debug)
- fprintf (stderr, "%s on %s:%d: %s\n",
+ fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n",
name ? name : "(unnamed)", curfdp->taggedfname,
lineno, buffer + linecharno);
}
@@ -6589,7 +6592,7 @@ regex_tag_multiline (void)
static bool
nocase_tail (const char *cp)
{
- int len = 0;
+ ptrdiff_t len = 0;
while (*cp != '\0' && c_tolower (*cp) == c_tolower (dbp[len]))
cp++, len++;
@@ -6648,7 +6651,7 @@ get_lispy_tag (register char *bp)
* If multi-line regular expressions are requested, each line read is
* appended to `filebuf'.
*/
-static long
+static ptrdiff_t
readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
{
char *buffer = lbp->buffer;
@@ -6664,8 +6667,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
if (p == pend)
{
/* We're at the end of linebuffer: expand it. */
+ xrnew (buffer, lbp->size, 2);
lbp->size *= 2;
- xrnew (buffer, lbp->size, char);
p += buffer - lbp->buffer;
pend = buffer + lbp->size;
lbp->buffer = buffer;
@@ -6702,13 +6705,12 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */
{
/* Expand filebuf. */
+ xrnew (filebuf.buffer, filebuf.size, 2);
filebuf.size *= 2;
- xrnew (filebuf.buffer, filebuf.size, char);
}
- memcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
- filebuf.len += lbp->len;
- filebuf.buffer[filebuf.len++] = '\n';
- filebuf.buffer[filebuf.len] = '\0';
+ strcpy (mempcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len),
+ "\n");
+ filebuf.len += lbp->len + 1;
}
return lbp->len + chars_deleted;
@@ -6722,10 +6724,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
static void
readline (linebuffer *lbp, FILE *stream)
{
- long result;
-
linecharno = charno; /* update global char number of line start */
- result = readline_internal (lbp, stream, infilename); /* read line */
+ ptrdiff_t result = readline_internal (lbp, stream, infilename);
lineno += 1; /* increment global line number */
charno += result; /* increment global char number */
@@ -6737,10 +6737,10 @@ readline (linebuffer *lbp, FILE *stream)
/* Check whether this is a #line directive. */
if (result > 12 && strneq (lbp->buffer, "#line ", 6))
{
- unsigned int lno;
+ intmax_t lno;
int start = 0;
- if (sscanf (lbp->buffer, "#line %u \"%n", &lno, &start) >= 1
+ if (sscanf (lbp->buffer, "#line %"SCNdMAX" \"%n", &lno, &start) >= 1
&& start > 0) /* double quote character found */
{
char *endp = lbp->buffer + start;
@@ -6850,7 +6850,7 @@ readline (linebuffer *lbp, FILE *stream)
} /* if #line directives should be considered */
{
- int match;
+ ptrdiff_t match;
regexp *rp;
char *name;
@@ -6900,7 +6900,7 @@ readline (linebuffer *lbp, FILE *stream)
/* Force explicit tag name, if a name is there. */
pfnote (name, true, lbp->buffer, match, lineno, linecharno);
if (debug)
- fprintf (stderr, "%s on %s:%d: %s\n",
+ fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n",
name ? name : "(unnamed)", curfdp->taggedfname,
lineno, lbp->buffer);
}
@@ -6925,11 +6925,11 @@ savestr (const char *cp)
}
/*
- * Return a pointer to a space of size LEN+1 allocated with xnew where
- * the string CP has been copied for at most the first LEN characters.
+ * Return a pointer to a space of size LEN+1 allocated with xnew
+ * with a copy of CP (containing LEN bytes) followed by a NUL byte.
*/
static char *
-savenstr (const char *cp, int len)
+savenstr (const char *cp, ptrdiff_t len)
{
char *dp = xnew (len + 1, char);
dp[len] = '\0';
@@ -7013,13 +7013,9 @@ verror (char const *format, va_list ap)
static char *
concat (const char *s1, const char *s2, const char *s3)
{
- int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ ptrdiff_t len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
char *result = xnew (len1 + len2 + len3 + 1, char);
-
- strcpy (result, s1);
- strcpy (result + len1, s2);
- strcpy (result + len1 + len2, s3);
-
+ strcpy (stpcpy (stpcpy (result, s1), s2), s3);
return result;
}
@@ -7029,16 +7025,16 @@ concat (const char *s1, const char *s2, const char *s3)
static char *
etags_getcwd (void)
{
- int bufsize = 200;
+ ptrdiff_t bufsize = 200;
char *path = xnew (bufsize, char);
while (getcwd (path, bufsize) == NULL)
{
if (errno != ERANGE)
pfatal ("getcwd");
- bufsize *= 2;
free (path);
- path = xnew (bufsize, char);
+ path = xnmalloc (bufsize, 2 * sizeof *path);
+ bufsize *= 2;
}
canonicalize_filename (path);
@@ -7099,7 +7095,7 @@ static char *
relative_filename (char *file, char *dir)
{
char *fp, *dp, *afn, *res;
- int i;
+ ptrdiff_t i;
/* Find the common root of file and dir (with a trailing slash). */
afn = absolute_filename (file, cwd);
@@ -7282,32 +7278,54 @@ linebuffer_init (linebuffer *lbp)
/* Set the minimum size of a string contained in a linebuffer. */
static void
-linebuffer_setlen (linebuffer *lbp, int toksize)
+linebuffer_setlen (linebuffer *lbp, ptrdiff_t toksize)
{
- while (lbp->size <= toksize)
+ if (lbp->size <= toksize)
{
- lbp->size *= 2;
- xrnew (lbp->buffer, lbp->size, char);
+ ptrdiff_t multiplier = toksize / lbp->size + 1;
+ xrnew (lbp->buffer, lbp->size, multiplier);
+ lbp->size *= multiplier;
}
lbp->len = toksize;
}
-/* Like malloc but get fatal error if memory is exhausted. */
-static void * ATTRIBUTE_MALLOC
-xmalloc (size_t size)
+/* Memory allocators with a fatal error if memory is exhausted. */
+
+static void
+memory_full (void)
+{
+ fatal ("virtual memory exhausted");
+}
+
+static void *
+xmalloc (ptrdiff_t size)
{
+ if (SIZE_MAX < size)
+ memory_full ();
void *result = malloc (size);
if (result == NULL)
- fatal ("virtual memory exhausted");
+ memory_full ();
return result;
}
static void *
-xrealloc (void *ptr, size_t size)
+xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
{
- void *result = realloc (ptr, size);
- if (result == NULL)
- fatal ("virtual memory exhausted");
+ ptrdiff_t nbytes;
+ if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes))
+ memory_full ();
+ return xmalloc (nbytes);
+}
+
+static void *
+xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
+{
+ ptrdiff_t nbytes;
+ if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
+ memory_full ();
+ void *result = realloc (pa, nbytes);
+ if (!result)
+ memory_full ();
return result;
}