Fix error-related issues (#773)

* Mark `error` as a `format` function, to properly scan its format

* Fix the call to error() from parser.y:
  - Use '%s' to avoid passing an arbitrary format
  - Simplify yyerror overall

* Fix size parameter of %.*s format being an int... bonkers standard.

* Report the number of arguments required and provided on a STRFMT mismatch

* Add an assert to check for a very unlikely bug
This commit is contained in:
daid
2021-03-02 16:34:19 +01:00
committed by GitHub
parent 56071599e7
commit 5d6e0677d9
5 changed files with 17 additions and 24 deletions

View File

@@ -746,7 +746,7 @@ static void beginExpansion(size_t distance, uint8_t skip,
#define LOOKUP_PRE_NEST(exp) (exp)->totalLen += size - skip
#define LOOKUP_POST_NEST(exp) do { \
if (name && ++depth >= nMaxRecursionDepth) \
fatalerror("Recursion limit (%u) exceeded\n", nMaxRecursionDepth); \
fatalerror("Recursion limit (%zu) exceeded\n", nMaxRecursionDepth); \
} while (0)
lookupExpansion(parent, distance);
#undef LOOKUP_PRE_NEST
@@ -851,7 +851,7 @@ static int peekInternal(uint8_t distance)
assert(writeIndex + (size) <= LEXER_BUF_SIZE); \
nbCharsRead = read(lexerState->fd, &lexerState->buf[writeIndex], (size)); \
if (nbCharsRead == -1) \
fatalerror("Error while reading \"%s\": %s\n", lexerState->path, errno); \
fatalerror("Error while reading \"%s\": %s\n", lexerState->path, strerror(errno)); \
totalCharsRead += nbCharsRead; \
writeIndex += nbCharsRead; \
if (writeIndex == LEXER_BUF_SIZE) \

View File

@@ -276,13 +276,8 @@ static void strfmt(char *dest, size_t destLen, char const *fmt, size_t nbArgs, s
dest[i++] = '%';
a++;
continue;
} else if (a == nbArgs) {
error("STRFMT: Not enough arguments for format spec\n", a + 1);
dest[i++] = '%';
a++;
continue;
} else if (a > nbArgs) {
// already warned for a == nbArgs
} else if (a >= nbArgs) {
// Will warn after formatting is done.
dest[i++] = '%';
a++;
continue;
@@ -301,6 +296,8 @@ static void strfmt(char *dest, size_t destLen, char const *fmt, size_t nbArgs, s
if (a < nbArgs)
error("STRFMT: %zu unformatted argument(s)\n", nbArgs - a);
else if (a > nbArgs)
error("STRFMT: Not enough arguments for format spec, got: %zu, need: %zu\n", nbArgs, a);
if (i > destLen - 1) {
warning(WARNING_LONG_STR, "STRFMT: String too long, got truncated\n");
@@ -366,14 +363,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
void yyerror(char const *str)
{
size_t len = strlen(str);
char *buf = malloc(len + 2);
memcpy(buf, str, len);
buf[len] = '\n';
buf[len + 1] = '\0';
error(buf);
free(buf);
error("%s\n", str);
}
// The CPU encodes instructions in a logical way, so most instructions actually follow patterns.

View File

@@ -13,6 +13,7 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -537,8 +538,10 @@ struct Symbol *sym_AddLocalLabel(char const *name)
* Check that `labelScope[i]` ended the check, guaranteeing that `name` is at least
* as long, and then that this was the entirety of the `Parent` part of `name`.
*/
if (labelScope[i] != '\0' || name[i] != '.')
error("Not currently in the scope of '%.*s'\n", parentLen, name);
if (labelScope[i] != '\0' || name[i] != '.') {
assert(parentLen <= INT_MAX);
error("Not currently in the scope of '%.*s'\n", (int)parentLen, name);
}
if (strchr(&name[parentLen + 1], '.')) /* There will at least be a terminator */
fatalerror("'%s' is a nonsensical reference to a nested local label\n",
name);
@@ -568,7 +571,7 @@ static uint32_t anonLabelID;
struct Symbol *sym_AddAnonLabel(void)
{
if (anonLabelID == UINT32_MAX) {
error("Only %" PRIu32 " anonymous labels can be created!");
error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID);
return NULL;
}
char name[MAXSYMLEN + 1];