~sircmpwn/harec

41638b8bebc72a86b5d275376d43a1059777416d — Sebastian 3 months ago 3fec6cd
parse: ensure identifier length doesn't exceed max

Signed-off-by: Sebastian <sebastian@sebsite.pw>
3 files changed, 34 insertions(+), 0 deletions(-)

M include/identifier.h
M src/parse.c
M tests/26-regression.ha
M include/identifier.h => include/identifier.h +6 -0
@@ 4,6 4,12 @@
#include <stdbool.h>
#include <stdint.h>

// Maximum length of an identifier, as the sum of the lengths (excluding NUL
// terminators) of its parts plus one for each namespace deliniation.
//
// In other words, the length of "a::b::c" is 5.
#define IDENT_MAX 255

struct identifier {
	char *name;
	struct identifier *ns;

M src/parse.c => src/parse.c +14 -0
@@ 108,13 108,19 @@ bool
parse_identifier(struct lexer *lexer, struct identifier *ident, bool trailing)
{
	struct token tok = {0};
	struct location loc = {0};
	struct identifier *i = ident;
	*ident = (struct identifier){0};
	size_t len = 0;
	bool found_trailing = false;
	while (!i->name) {
		switch (lex(lexer, &tok)) {
		case T_NAME:
			len += strlen(tok.name);
			i->name = xstrdup(tok.name);
			if (loc.file == 0) {
				loc = tok.loc;
			}
			token_finish(&tok);
			break;
		default:


@@ 130,6 136,7 @@ parse_identifier(struct lexer *lexer, struct identifier *ident, bool trailing)
		struct identifier *ns;
		switch (lex(lexer, &tok)) {
		case T_DOUBLE_COLON:
			len++;
			ns = xcalloc(1, sizeof(struct identifier));
			*ns = *i;
			i->ns = ns;


@@ 140,6 147,13 @@ parse_identifier(struct lexer *lexer, struct identifier *ident, bool trailing)
			break;
		}
	}

	if (len > IDENT_MAX) {
		xfprintf(stderr, "%s:%d:%d: identifier exceeds maximum length\n",
			sources[loc.file], loc.lineno, loc.colno);
		errline(loc);
		exit(EXIT_FAILURE);
	}
	return found_trailing;
}


M tests/26-regression.ha => tests/26-regression.ha +14 -0
@@ 190,4 190,18 @@ export fn main() void = {

	control_never();
	assert(rt::compile("fn a() void = { abort(): int; };") as rt::exited != rt::EXIT_SUCCESS);

	// identifier exceeds maximum length
	let buf: [1024]u8 = [0...];
	let buf = buf[..0];
	static append(buf, rt::toutf8("let a")...);
	// IDENT_MAX (in identifier.h) is defined as 255
	for (let i = 0z; i < 255 / 2; i += 1) {
		static append(buf, rt::toutf8("::a")...);
	};
	const n = len(buf);
	static append(buf, rt::toutf8(" = 0;")...);
	assert(rt::compile(*(&buf: *str)) as rt::exited == rt::EXIT_SUCCESS);
	static insert(buf[n], rt::toutf8("::a")...);
	assert(rt::compile(*(&buf: *str)) as rt::exited != rt::EXIT_SUCCESS);
};