From 7c8e3dd4fd1486bfa274d6219974d7ce7d357649 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 18 Aug 2025 12:02:00 +0200 Subject: [PATCH] Fix max module name to 31 chars and the entire module path to 63 characters. --- releasenotes.md | 1 + src/compiler/compiler_internal.h | 2 ++ src/compiler/parse_global.c | 34 ++++++++++++++++++++-- src/utils/file_utils.c | 6 ++-- test/test_suite/module/module_long_name.c3 | 17 +++++++++++ test/test_suite/module/module_short.c3t | 10 +++++++ 6 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 test/test_suite/module/module_long_name.c3 create mode 100644 test/test_suite/module/module_short.c3t diff --git a/releasenotes.md b/releasenotes.md index c3b03479a..bdbfa9dc2 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -14,6 +14,7 @@ - Methods ignore visibility settings. - Allow inout etc on untyped macro parameters even if they are not pointers. - Deprecate `add_array` in favour of `push_all` on lists. +- Fix max module name to 31 chars and the entire module path to 63 characters. ### Fixes - List.remove_at would incorrectly trigger ASAN. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 663ba6613..86aa8cd8c 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -52,6 +52,8 @@ typedef uint16_t FileId; #define MAX_PRIORITY 0xFFFF #define MAX_TYPE_SIZE UINT32_MAX #define MAX_GLOBAL_DECL_STACK (65536) +#define MAX_MODULE_NAME 31 +#define MAX_MODULE_PATH 63 #define MEMCMP_INLINE_REGS 8 #define UINT128_MAX ((Int128) { UINT64_MAX, UINT64_MAX }) #define INT128_MAX ((Int128) { INT64_MAX, UINT64_MAX }) diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 485454f9f..a7eabc944 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -98,9 +98,11 @@ static inline Path *parse_module_path(ParseContext *c) ASSERT(tok_is(c, TOKEN_IDENT)); scratch_buffer_clear(); SourceSpan span = c->span; + int max_exceeded = 0; while (1) { const char *string = symstr(c); + size_t len = c->data.lex_len; if (!try_consume(c, TOKEN_IDENT)) { if (token_is_keyword_ident(c->tok)) @@ -116,13 +118,41 @@ static inline Path *parse_module_path(ParseContext *c) PRINT_ERROR_HERE("Each '::' must be followed by a regular lower case sub module name."); return NULL; } - scratch_buffer_append(string); + if (len > MAX_MODULE_NAME) + { + PRINT_ERROR_LAST("The module name is too long, it's %d characters (%d more than the maximum allowed %d characters).", (int)len, (int)len - MAX_MODULE_NAME, MAX_MODULE_NAME); + return NULL; + } + if (max_exceeded) + { + max_exceeded += len; + } + else + { + scratch_buffer_append(string); + if (scratch_buffer.len > MAX_MODULE_PATH) + { + max_exceeded = scratch_buffer.len; + } + } if (!try_consume(c, TOKEN_SCOPE)) { span = extend_span_with_token(span, c->prev_span); break; } - scratch_buffer_append("::"); + if (max_exceeded) + { + max_exceeded += 2; + } + else + { + scratch_buffer_append("::"); + } + } + // This way we can highlight the entire span. + if (max_exceeded) + { + print_error_at(extend_span_with_token(span, c->prev_span), "The full module path is too long, it's %lld characters (%lld more than the maximum allowed %lld characters).", (long long int)max_exceeded, (long long int)max_exceeded - MAX_MODULE_PATH, (long long int)MAX_MODULE_PATH); } return path_create_from_string(scratch_buffer_to_string(), scratch_buffer.len, span); } diff --git a/src/utils/file_utils.c b/src/utils/file_utils.c index 142708884..b3f678708 100644 --- a/src/utils/file_utils.c +++ b/src/utils/file_utils.c @@ -207,8 +207,8 @@ bool file_namesplit(const char *path, char** filename_ptr, char** directory_ptr) } } size_t file_len = (found_at != ((size_t)-1)) ? len - found_at - 1 : len; - if (file_len == 1 && path[0] == '.') return false; - if (file_len == 2 && path[0] == '.' && path[1] == '.') return false; + if (file_len == 1 && path[found_at + 1] == '.') return false; + if (file_len == 2 && path[found_at + 1] == '.' && path[found_at + 2] == '.') return false; if (!file_len) return false; if (filename_ptr) *filename_ptr = str_copy(&path[len - file_len], file_len); if (!directory_ptr) return true; @@ -476,7 +476,7 @@ void file_create_folders(const char *name) char *dir; if (!file_namesplit(path, NULL, &dir)) { - error_exit("Failed to split %s", filename); + error_exit("Failed to split %s", name); } if (str_eq(dir, ".") || dir[0] == '\0') return; if (!file_exists(dir)) dir_make_recursive(dir); diff --git a/test/test_suite/module/module_long_name.c3 b/test/test_suite/module/module_long_name.c3 new file mode 100644 index 000000000..5a85a2e93 --- /dev/null +++ b/test/test_suite/module/module_long_name.c3 @@ -0,0 +1,17 @@ +module a1234567890123456789012345678901; // #error: The module name is too long + +fn void main() +{ +} + +module a123456789012345678901234567890::ifjeijfoiejfoejifojeiofjioe::ifjeijiefjiefj; + +fn void foo() +{ +} + +module a123456789012345678901234567890::ifjeijfoiejfoejieiofjioe::ifjeijiji::efj::fefeif::ofjiwjfe; // #error: The full module path is too long + +fn void foo() +{ +} \ No newline at end of file diff --git a/test/test_suite/module/module_short.c3t b/test/test_suite/module/module_short.c3t new file mode 100644 index 000000000..3dc21bc5a --- /dev/null +++ b/test/test_suite/module/module_short.c3t @@ -0,0 +1,10 @@ +module a; +import b, std; + +fn void main() +{ + io::printn(b::test()); +} + +module b; +fn int test() => 37; \ No newline at end of file