-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
The logic is ported from Golang to C. Reference code: https://cs.opensource.google/go/go/+/refs/tags/go1.21.4:src/path/path.go;l=70
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ | |
*/ | ||
|
||
#include <stdint.h> | ||
#include <stdlib.h> | ||
Check warning Code scanning / Cppcheck (reported by Codacy) Include file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning
Include file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
|
||
#include <string.h> | ||
Check warning Code scanning / Cppcheck (reported by Codacy) Include file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning
Include file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
|
||
#include <sys/time.h> | ||
#include <time.h> | ||
|
||
|
@@ -67,3 +69,98 @@ void rv_clock_gettime(struct timespec *tp) | |
tp->tv_sec = tv_sec; | ||
tp->tv_nsec = tv_usec / 1000; /* Transfer to microseconds */ | ||
} | ||
|
||
char *sanitize_path(const char *orig_path) | ||
{ | ||
size_t n = strlen(orig_path); | ||
Check warning Code scanning / Semgrep (reported by Codacy) The strlen family of functions does not handle strings that are not null terminated. This can lead to buffer over reads and cause the application to crash by accessing unintended memory locations. It is recommended that strnlen be used instead as a maxlen value can be provided. For more information please see: https://linux.die.net/man/3/strnlen If developing for C Runtime Library (CRT), more secure versions of these functions should be used, see: https://learn.microsoft.com/en-us/cpp/c- Warning
The strlen family of functions does not handle strings that are not null
terminated. This can lead to buffer over reads and cause the application to crash by accessing unintended memory locations. It is recommended that strnlen be used instead as a maxlen value can be provided. For more information please see: https://linux.die.net/man/3/strnlen If developing for C Runtime Library (CRT), more secure versions of these functions should be used, see: https://learn.microsoft.com/en-us/cpp/c- Check notice Code scanning / Flawfinder (reported by Codacy) Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). Note
Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126).
|
||
|
||
char *ret = (char *) malloc(n + 1); | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 21.3 rule Note
MISRA 21.3 rule
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
|
||
memset(ret, '\0', n + 1); | ||
Check warning Code scanning / Semgrep (reported by Codacy) When handling sensitive information in a buffer, it's important to ensure that the data is securely erased before the buffer is deleted or reused. Warning
When handling sensitive information in a buffer, it's important to ensure that the data is securely erased before the buffer is deleted or reused.
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 17.7 rule Note
MISRA 17.7 rule
|
||
|
||
/* After sanitization, the new path will only be shorter than the original | ||
* one. Thus, we can reuse the space */ | ||
if (strlen(orig_path) == 0) { | ||
Check warning Code scanning / Semgrep (reported by Codacy) The strlen family of functions does not handle strings that are not null terminated. This can lead to buffer over reads and cause the application to crash by accessing unintended memory locations. It is recommended that strnlen be used instead as a maxlen value can be provided. For more information please see: https://linux.die.net/man/3/strnlen If developing for C Runtime Library (CRT), more secure versions of these functions should be used, see: https://learn.microsoft.com/en-us/cpp/c- Warning
The strlen family of functions does not handle strings that are not null
terminated. This can lead to buffer over reads and cause the application to crash by accessing unintended memory locations. It is recommended that strnlen be used instead as a maxlen value can be provided. For more information please see: https://linux.die.net/man/3/strnlen If developing for C Runtime Library (CRT), more secure versions of these functions should be used, see: https://learn.microsoft.com/en-us/cpp/c- Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
Check notice Code scanning / Flawfinder (reported by Codacy) Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). Note
Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126).
|
||
ret[0] = '.'; | ||
return ret; | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 15.5 rule Note
MISRA 15.5 rule
|
||
} | ||
|
||
int rooted = (orig_path[0] == '/'); | ||
Check warning Code scanning / Cppcheck (reported by Codacy) misra violation 1003 with no text in the supplied rule-texts-file Warning
misra violation 1003 with no text in the supplied rule-texts-file
|
||
|
||
/* | ||
* Invariants: | ||
* reading from path; r is index of next byte to process -> path[r] | ||
* writing to buf; w is index of next byte to write -> ret[strlen(ret)] | ||
* dotdot is index in buf where .. must stop, either because | ||
* a) it is the leading slash | ||
* b) it is a leading ../../.. prefix. | ||
*/ | ||
size_t w = 0; | ||
size_t r = 0; | ||
size_t dotdot = 0; | ||
if (rooted) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 14.4 rule Note
MISRA 14.4 rule
|
||
ret[w] = '/'; | ||
w++; | ||
r = 1; | ||
dotdot = 1; | ||
} | ||
|
||
while (r < n) { | ||
if (orig_path[r] == '/') { | ||
/* empty path element */ | ||
r++; | ||
} else if (orig_path[r] == '.' && | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
(r + 1 == n || orig_path[r + 1] == '/')) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
|
||
/* . element */ | ||
r++; | ||
} else if (orig_path[r] == '.' && orig_path[r + 1] == '.' && | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
(r + 2 == n || orig_path[r + 2] == '/')) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
/* .. element: remove to last / */ | ||
r += 2; | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
|
||
|
||
if (w > dotdot) { | ||
/* can backtrack */ | ||
w--; | ||
while (w > dotdot && ret[w] != '/') { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
w--; | ||
} | ||
} else if (!rooted) { | ||
/* cannot backtrack, but not rooted, so append .. element. */ | ||
if (w > 0) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
|
||
ret[w] = '/'; | ||
w++; | ||
} | ||
ret[w] = '.'; | ||
w++; | ||
ret[w] = '.'; | ||
w++; | ||
dotdot = w; | ||
} | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 15.7 rule Note
MISRA 15.7 rule
|
||
} else { | ||
/* real path element. | ||
add slash if needed */ | ||
if ((rooted && w != 1) || (!rooted && w != 0)) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
ret[w] = '/'; | ||
w++; | ||
} | ||
|
||
/* copy element */ | ||
for (; r < n && orig_path[r] != '/'; r++) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
ret[w] = orig_path[r]; | ||
w++; | ||
} | ||
} | ||
// printf("w = %ld, r = %ld, dotdot = %ld\nret = %s\n", w, r, dotdot, | ||
// ret); | ||
} | ||
|
||
/* Turn empty string into "." */ | ||
if (w == 0) { | ||
Check notice Code scanning / Cppcheck (reported by Codacy) MISRA 10.4 rule Note
MISRA 10.4 rule
|
||
ret[w] = '.'; | ||
w++; | ||
} | ||
|
||
for (size_t i = w; i < n; i++) { | ||
ret[i] = '\0'; | ||
} | ||
return ret; | ||
} |