Skip to content

Commit 49d0b26

Browse files
committed
add normalizepath_cstr()
1 parent 5ae9008 commit 49d0b26

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

include/filelib.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,18 @@
99
char* getFileExt(const char* filename, size_t fnlen);
1010
time_t getFileModTime(const char* filename);
1111
size_t getfilesize(char* filename);
12-
int normalizepath(stringptr* path);
1312
ssize_t getpathdiff(stringptr* path1, stringptr* path2, char* workbuf);
1413
char* ulz_mkdtemp(char* templ);
1514
size_t mktempdir(const char* prefix, char* buffer, size_t bufsize);
1615
char* getfilename(stringptr* path);
16+
int normalizepath(stringptr* path);
17+
/* removes multiple slashes, /./ style stuff and resolves ../ kind of stuff on _absolute_ paths.
18+
* will always strip trailing slashes.
19+
* will fail with relative paths. does not resolve symlinks.
20+
* out must point to a buffer of sufficient size, which equals (worst case) strlen(path)+1.
21+
* returns 0 on failure, on success out.
22+
*/
23+
char* normalizepath_cstr(const char* path, char* out);
1724

1825
#pragma RcB2 DEP "../src/filelib/*.c"
1926

src/filelib/normalizepath_cstr.c

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#undef _POSIX_C_SOURCE
2+
#define _POSIX_C_SOURCE 200809L
3+
#include <stddef.h>
4+
#include <string.h>
5+
6+
/* removes multiple slashes, /./ style stuff and resolves ../ kind of stuff on _absolute_ paths.
7+
* will always strip trailing slashes.
8+
* will fail with relative paths. does not resolve symlinks.
9+
* out must point to a buffer of sufficient size, which equals (worst case) strlen(path)+1.
10+
* returns 0 on failure, on success out.
11+
*/
12+
char* normalizepath_cstr(const char* path, char* out) {
13+
size_t i, out_size = 0;
14+
char* tmp;
15+
#if defined(__psp__) || defined(PSPLIKE_PATH)
16+
/* psp paths are a mix of DOS and unix, with a drive name + colon,
17+
followed by a unix path, e.g. ms0:/PSP */
18+
for(i = 0; path[i]; ++i) {
19+
out[out_size++] = path[i];
20+
if(path[i] == '/') {
21+
--out_size;
22+
if(i > 0 && path[i-1] != ':') goto fail;
23+
break;
24+
}
25+
}
26+
#else
27+
i = 0;
28+
#endif
29+
if(path[i] != '/') goto fail;
30+
for(; path[i]; i++) {
31+
switch(path[i]) {
32+
case '/':
33+
while(path[i+1] == '/') i++;
34+
if(!out_size || out[out_size -1] != '/') goto copy;
35+
break;
36+
case '.':
37+
if(!i || !out_size) goto fail;
38+
else if(path[i-1] == '/' && out[out_size -1] == '/') {
39+
out_size--;
40+
switch(path[i+1]) {
41+
case '.':
42+
if((!path[i+2] || path[i+2] == '/')) {
43+
tmp = out + out_size;
44+
while(--tmp > out && *tmp != '/');
45+
if(tmp >= out && *tmp == '/') {
46+
out_size = tmp - out;
47+
i += 2;
48+
goto restore;
49+
} else {
50+
fail:
51+
return 0;
52+
}
53+
}
54+
goto def;
55+
case '/':
56+
i++;
57+
restore:
58+
out_size++;
59+
if(!path[i]) goto done;
60+
break;
61+
case 0:
62+
goto restore;
63+
default:
64+
def:
65+
out_size++;
66+
goto copy;
67+
break;
68+
}
69+
} else goto copy;
70+
break;
71+
default:
72+
copy:
73+
out[out_size++] = path[i];
74+
break;
75+
}
76+
}
77+
done:
78+
if(out_size > 1 && out[out_size -1] == '/')
79+
out_size--; // remove trailing slash
80+
out[out_size] = 0;
81+
return out;
82+
}
83+
84+
#ifdef FUZZER_TEST
85+
#include <sys/mman.h>
86+
#include <stdio.h>
87+
int main(int a, char**b) {
88+
char buf[64], wb[64];
89+
if(a == 3 && b[1][0] == 'X' && !b[1][1]) {
90+
if(normalizepath_cstr(b[2], buf))
91+
printf("%s -> %s\n" , b[2], buf);
92+
return 0;
93+
}
94+
FILE *f;
95+
if(a == 2 && (f = fopen(b[1], "r")) && fgets(buf, sizeof buf, f)) {
96+
size_t l = strlen(buf); if(l) buf[l-1] = 0; else return 1;
97+
char *page2 = mmap(0, 4096, PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
98+
char* page = mmap(0, 4096, PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
99+
if(!page) return 1;
100+
if(!page2) return 1;
101+
if(page2-page!=4096) return 1;
102+
char* ns = page+4096-l;
103+
memcpy(ns, buf, l);
104+
if (normalizepath_cstr(ns, wb))
105+
printf("%s -> %s\n" , ns, wb);
106+
fclose(f);
107+
return 0;
108+
}
109+
return 1;
110+
}
111+
#endif

0 commit comments

Comments
 (0)