| 1239 | } |
| 1240 | |
| 1241 | static int jl_apply_edits(const char *source, size_t source_length, jl_edit_t *edits, |
| 1242 | size_t edit_count, char **result_out, size_t *result_length_out) { |
| 1243 | if (edit_count == 2U && edits[1].start < edits[0].start) { |
| 1244 | jl_edit_t swap = edits[0]; |
| 1245 | edits[0] = edits[1]; |
| 1246 | edits[1] = swap; |
| 1247 | } |
| 1248 | size_t result_length = source_length; |
| 1249 | size_t previous_end = 0; |
| 1250 | for (size_t i = 0; i < edit_count; i++) { |
| 1251 | if (edits[i].start < previous_end || edits[i].end < edits[i].start || |
| 1252 | edits[i].end > source_length) { |
| 1253 | return -1; |
| 1254 | } |
| 1255 | size_t removed = edits[i].end - edits[i].start; |
| 1256 | if (removed > result_length) { |
| 1257 | return -1; |
| 1258 | } |
| 1259 | result_length -= removed; |
| 1260 | if (edits[i].replacement_length > SIZE_MAX - result_length) { |
| 1261 | return -1; |
| 1262 | } |
| 1263 | result_length += edits[i].replacement_length; |
| 1264 | previous_end = edits[i].end; |
| 1265 | } |
| 1266 | if (result_length > JL_MAX_FILE_BYTES || result_length == SIZE_MAX) { |
| 1267 | return -1; |
| 1268 | } |
| 1269 | |
| 1270 | char *result = malloc(result_length + 1U); |
| 1271 | if (!result) { |
| 1272 | return -1; |
| 1273 | } |
| 1274 | size_t source_pos = 0; |
| 1275 | size_t result_pos = 0; |
| 1276 | for (size_t i = 0; i < edit_count; i++) { |
| 1277 | size_t prefix_length = edits[i].start - source_pos; |
| 1278 | memcpy(result + result_pos, source + source_pos, prefix_length); |
| 1279 | result_pos += prefix_length; |
| 1280 | if (edits[i].replacement_length > 0U) { |
| 1281 | memcpy(result + result_pos, edits[i].replacement, edits[i].replacement_length); |
| 1282 | result_pos += edits[i].replacement_length; |
| 1283 | } |
| 1284 | source_pos = edits[i].end; |
| 1285 | } |
| 1286 | memcpy(result + result_pos, source + source_pos, source_length - source_pos); |
| 1287 | result_pos += source_length - source_pos; |
| 1288 | result[result_pos] = '\0'; |
| 1289 | *result_out = result; |
| 1290 | *result_length_out = result_pos; |
| 1291 | return 0; |
| 1292 | } |
| 1293 | |
| 1294 | static bool jl_snapshot_state_equal(const jl_file_snapshot_t *left, |
| 1295 | const jl_file_snapshot_t *right) { |
no outgoing calls
no test coverage detected