diff options
| author | Paul Eggert | 2024-04-30 01:20:12 -0700 |
|---|---|---|
| committer | Paul Eggert | 2024-04-30 01:26:21 -0700 |
| commit | 7e2309c6fc67b8149cc4c75f8d7f5f93e60b86c7 (patch) | |
| tree | 313451a2a683aae3be0e04a043be0c3ea9c6dbfb /lib-src | |
| parent | de59c02c685189413c7c5a136224d10152dc8a61 (diff) | |
| download | emacs-7e2309c6fc67b8149cc4c75f8d7f5f93e60b86c7.tar.gz emacs-7e2309c6fc67b8149cc4c75f8d7f5f93e60b86c7.zip | |
etags: fix #line parsing (\\", long lines)
* lib-src/etags.c (readline): Don’t mishandle lines like
‘#line 1 "a//"’, which has an escaped backslash before ‘"’.
Don’t mishandle lines so long that sscanf overflows %n.
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/etags.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c index c316b3c7649..57ffbce380c 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c | |||
| @@ -7375,26 +7375,26 @@ readline (linebuffer *lbp, FILE *stream) | |||
| 7375 | /* Check whether this is a #line directive. */ | 7375 | /* Check whether this is a #line directive. */ |
| 7376 | if (result > 12 && strneq (lbp->buffer, "#line ", 6)) | 7376 | if (result > 12 && strneq (lbp->buffer, "#line ", 6)) |
| 7377 | { | 7377 | { |
| 7378 | intmax_t lno; | 7378 | char *lno_start = lbp->buffer + 6; |
| 7379 | int start = 0; | 7379 | char *lno_end; |
| 7380 | intmax_t lno = strtoimax (lno_start, &lno_end, 10); | ||
| 7381 | char *quoted_filename | ||
| 7382 | = lno_start < lno_end ? skip_spaces (lno_end) : NULL; | ||
| 7380 | 7383 | ||
| 7381 | if (sscanf (lbp->buffer, "#line %"SCNdMAX" \"%n", &lno, &start) >= 1 | 7384 | if (quoted_filename && *quoted_filename == '"') |
| 7382 | && start > 0) /* double quote character found */ | ||
| 7383 | { | 7385 | { |
| 7384 | char *endp = lbp->buffer + start; | 7386 | char *endp = quoted_filename; |
| 7387 | while (*++endp && *endp != '"') | ||
| 7388 | endp += *endp == '\\' && endp[1]; | ||
| 7385 | 7389 | ||
| 7386 | while ((endp = strchr (endp, '"')) != NULL | 7390 | if (*endp) |
| 7387 | && endp[-1] == '\\') | ||
| 7388 | endp++; | ||
| 7389 | if (endp != NULL) | ||
| 7390 | /* Ok, this is a real #line directive. Let's deal with it. */ | 7391 | /* Ok, this is a real #line directive. Let's deal with it. */ |
| 7391 | { | 7392 | { |
| 7392 | char *taggedabsname; /* absolute name of original file */ | 7393 | char *taggedabsname; /* absolute name of original file */ |
| 7393 | char *taggedfname; /* name of original file as given */ | 7394 | char *taggedfname; /* name of original file as given */ |
| 7394 | char *name; /* temp var */ | 7395 | char *name = quoted_filename + 1; |
| 7395 | 7396 | ||
| 7396 | discard_until_line_directive = false; /* found it */ | 7397 | discard_until_line_directive = false; /* found it */ |
| 7397 | name = lbp->buffer + start; | ||
| 7398 | *endp = '\0'; | 7398 | *endp = '\0'; |
| 7399 | canonicalize_filename (name); | 7399 | canonicalize_filename (name); |
| 7400 | taggedabsname = absolute_filename (name, tagfiledir); | 7400 | taggedabsname = absolute_filename (name, tagfiledir); |