commit - 63df5c26a981d4ade2f1fec2b76b2e0e8ae21c24
commit + 977d6ed4e3bf4b0a88036eca24b76fd2258cfd40
blob - bcbf226c4da428bbbfd391e07e354db1ec652a06
blob + 233089193efb29e5bde381f749138a357826ffa3
--- FICS/makerank.c
+++ FICS/makerank.c
static ENTRY **list;
static ENTRY **sortme;
+
+// Returns 1 if filename is safe, 0 otherwise
+static int is_valid_filename(const char *name) {
+ // Reject empty string
+ if (!name || !*name)
+ return 0;
+ // Reject if starts with '.' (hidden files, ".", "..")
+ if (name[0] == '.')
+ return 0;
+ // Reject if contains "..", '/', '\\', or starts with '/'
+ if (strstr(name, "..") || strchr(name, '/') || strchr(name, '\\') || name[0] == '/')
+ return 0;
+ // Reject if contains whitespace or control characters
+ for (const char *p = name; *p; ++p) {
+ if (isspace((unsigned char)*p) || iscntrl((unsigned char)*p))
+ return 0;
+ }
+ // Optionally, restrict to alphanumeric and a few safe symbols
+ for (const char *p = name; *p; ++p) {
+ if (!isalnum((unsigned char)*p) && *p != '-' && *p != '_' && *p != '.') {
+ return 0;
+ }
+ }
+ return 1;
+}
+
static char *rnames[] = { "std", "blitz", "wild", "lightning" };
static int rtype;
* Validate that e.name does not contain path
* traversal or separators
*/
- if (strstr(e.name, "..") ||
- strchr(e.name, '/') ||
- strchr(e.name, '\\')) {
+ if (!is_valid_filename(e.name)) {
printf("Skipping invalid filename: %s\n",
e.name);
continue;