Normalize an untrusted repository-relative path without touching the * filesystem. Absolute paths, drive/UNC paths, control bytes, and any `..` * component are rejected. A root scope (`.`) normalizes to the empty prefix. */
| 4126 | * filesystem. Absolute paths, drive/UNC paths, control bytes, and any `..` |
| 4127 | * component are rejected. A root scope (`.`) normalizes to the empty prefix. */ |
| 4128 | static coverage_path_result_t coverage_normalize_rel(const char *input, bool allow_root, char *out, |
| 4129 | size_t out_size) { |
| 4130 | if (!input || !out || out_size == 0U) { |
| 4131 | return COVERAGE_PATH_INVALID; |
| 4132 | } |
| 4133 | out[0] = '\0'; |
| 4134 | size_t len = strlen(input); |
| 4135 | if (len == 0U || len >= out_size || input[0] == '/' || input[0] == '\\' || |
| 4136 | (len >= 2U && isalpha((unsigned char)input[0]) && input[1] == ':')) { |
| 4137 | return COVERAGE_PATH_OUTSIDE; |
| 4138 | } |
| 4139 | |
| 4140 | size_t in = 0U; |
| 4141 | size_t written = 0U; |
| 4142 | while (in < len) { |
| 4143 | while (in < len && (input[in] == '/' || input[in] == '\\')) { |
| 4144 | in++; |
| 4145 | } |
| 4146 | if (in >= len) { |
| 4147 | break; |
| 4148 | } |
| 4149 | size_t start = in; |
| 4150 | while (in < len && input[in] != '/' && input[in] != '\\') { |
| 4151 | unsigned char c = (unsigned char)input[in]; |
| 4152 | if (c < 0x20U) { |
| 4153 | return COVERAGE_PATH_INVALID; |
| 4154 | } |
| 4155 | in++; |
| 4156 | } |
| 4157 | size_t part_len = in - start; |
| 4158 | if (part_len == 1U && input[start] == '.') { |
| 4159 | continue; |
| 4160 | } |
| 4161 | if (part_len == 2U && input[start] == '.' && input[start + 1U] == '.') { |
| 4162 | return COVERAGE_PATH_OUTSIDE; |
| 4163 | } |
| 4164 | if (written > 0U) { |
| 4165 | if (written + 1U >= out_size) { |
| 4166 | return COVERAGE_PATH_INVALID; |
| 4167 | } |
| 4168 | out[written++] = '/'; |
| 4169 | } |
| 4170 | if (written + part_len >= out_size) { |
| 4171 | return COVERAGE_PATH_INVALID; |
| 4172 | } |
| 4173 | memcpy(out + written, input + start, part_len); |
| 4174 | written += part_len; |
| 4175 | } |
| 4176 | out[written] = '\0'; |
| 4177 | return written > 0U || allow_root ? COVERAGE_PATH_OK : COVERAGE_PATH_INVALID; |
| 4178 | } |
| 4179 | |
| 4180 | static int64_t coverage_stat_mtime_ns(const struct stat *st) { |
| 4181 | #ifdef __APPLE__ |
no outgoing calls
no test coverage detected