Changeset View
Standalone View
usr.bin/bsdiff/bspatch/bspatch.c
Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
exit_cleanup(void) | exit_cleanup(void) | ||||
{ | { | ||||
if (dirfd != -1 && newfile != NULL) | if (dirfd != -1 && newfile != NULL) | ||||
if (unlinkat(dirfd, newfile, 0)) | if (unlinkat(dirfd, newfile, 0)) | ||||
warn("unlinkat"); | warn("unlinkat"); | ||||
} | } | ||||
static off_t | |||||
delphij: Maybe inline? | |||||
add_off_t(off_t a, off_t b) | |||||
{ | |||||
off_t result; | |||||
#if __GNUC__ >= 5 || \ | |||||
(defined(__has_builtin) && __has_builtin(__builtin_add_overflow)) | |||||
if (__builtin_add_overflow(a, b, &result) | |||||
errx(1, "Corrupt patch"); | |||||
kibUnsubmitted Not Done Inline ActionsIs this variant of the code so much better than explicit overflow checks below that it warrants coding the same check twice ? You need to do the explicit check anyway, so why bother ? What can be done, instead, is to add e.g. sys/cdefs.h macro ADD_OF_CHECKED(a,b,result) and make this functionality generally useful, to avoid open-coding the same fragment several times. typeof() macro or generic C11 facility would allow to make that type-neutral. kib: Is this variant of the code so much better than explicit overflow checks below that it warrants… | |||||
kibUnsubmitted Not Done Inline ActionsOr may be sys/param.h is better place. kib: Or may be sys/param.h is better place. | |||||
emasteAuthorUnsubmitted Not Done Inline ActionsWe could do away with the bzctrllen > OFF_MAX - HEADER_SIZE, bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen and bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen checks if we were so inclined. This approach is harder to get wrong (by missing an explicit overflow check), and is resilient to future changes in variable types. emaste: We could do away with the `bzctrllen > OFF_MAX - HEADER_SIZE`, `bzctrllen + HEADER_SIZE >… | |||||
#else | |||||
if ((b > 0 && a > OFF_MAX - b) || (b < 0 && a < OFF_MIN - b)) | |||||
errx(1, "Corrupt patch"); | |||||
result = a + b; | |||||
#endif | |||||
return result; | |||||
} | |||||
static off_t offtin(u_char *buf) | static off_t offtin(u_char *buf) | ||||
{ | { | ||||
off_t y; | off_t y; | ||||
y = buf[7] & 0x7F; | y = buf[7] & 0x7F; | ||||
y = y * 256; y += buf[6]; | y = y * 256; y += buf[6]; | ||||
y = y * 256; y += buf[5]; | y = y * 256; y += buf[5]; | ||||
y = y * 256; y += buf[4]; | y = y * 256; y += buf[4]; | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | #endif | ||||
/* Close patch file and re-open it via libbzip2 at the right places */ | /* Close patch file and re-open it via libbzip2 at the right places */ | ||||
if (fclose(f)) | if (fclose(f)) | ||||
err(1, "fclose(%s)", argv[3]); | err(1, "fclose(%s)", argv[3]); | ||||
offset = HEADER_SIZE; | offset = HEADER_SIZE; | ||||
if (fseeko(cpf, offset, SEEK_SET)) | if (fseeko(cpf, offset, SEEK_SET)) | ||||
err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | ||||
if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) | if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) | ||||
errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); | errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); | ||||
offset += bzctrllen; | offset = add_off_t(offset, bzctrllen); | ||||
if (fseeko(dpf, offset, SEEK_SET)) | if (fseeko(dpf, offset, SEEK_SET)) | ||||
err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | ||||
if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) | if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) | ||||
errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); | errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); | ||||
offset += bzdatalen; | offset = add_off_t(offset, bzdatalen); | ||||
if (fseeko(epf, offset, SEEK_SET)) | if (fseeko(epf, offset, SEEK_SET)) | ||||
err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); | ||||
if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) | if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) | ||||
errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); | errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); | ||||
if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || | if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || | ||||
oldsize > SSIZE_MAX || | oldsize > SSIZE_MAX || | ||||
(old = malloc(oldsize)) == NULL || | (old = malloc(oldsize)) == NULL || | ||||
Show All 17 Lines | while (newpos < newsize) { | ||||
} | } | ||||
/* Sanity-check */ | /* Sanity-check */ | ||||
if (ctrl[0] < 0 || ctrl[0] > INT_MAX || | if (ctrl[0] < 0 || ctrl[0] > INT_MAX || | ||||
ctrl[1] < 0 || ctrl[1] > INT_MAX) | ctrl[1] < 0 || ctrl[1] > INT_MAX) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Sanity-check */ | /* Sanity-check */ | ||||
if (newpos + ctrl[0] > newsize) | if (add_off_t(newpos, ctrl[0]) > newsize) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Read diff string */ | /* Read diff string */ | ||||
lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); | lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); | ||||
if ((lenread < ctrl[0]) || | if ((lenread < ctrl[0]) || | ||||
((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) | ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Add old data to diff string */ | /* Add old data to diff string */ | ||||
for (i = 0; i < ctrl[0]; i++) | for (i = 0; i < ctrl[0]; i++) | ||||
if ((oldpos + i >= 0) && (oldpos + i < oldsize)) | if (add_off_t(oldpos, i) < oldsize) | ||||
new[newpos + i] += old[oldpos + i]; | new[newpos + i] += old[oldpos + i]; | ||||
/* Adjust pointers */ | /* Adjust pointers */ | ||||
newpos += ctrl[0]; | newpos = add_off_t(newpos, ctrl[0]); | ||||
oldpos += ctrl[0]; | oldpos = add_off_t(oldpos, ctrl[0]); | ||||
/* Sanity-check */ | /* Sanity-check */ | ||||
if (newpos + ctrl[1] > newsize) | if (add_off_t(newpos, ctrl[1]) > newsize) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Read extra string */ | /* Read extra string */ | ||||
lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); | lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); | ||||
if ((lenread < ctrl[1]) || | if ((lenread < ctrl[1]) || | ||||
((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) | ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) | ||||
errx(1, "Corrupt patch"); | errx(1, "Corrupt patch"); | ||||
/* Adjust pointers */ | /* Adjust pointers */ | ||||
newpos+=ctrl[1]; | newpos = add_off_t(newpos, ctrl[1]); | ||||
oldpos+=ctrl[2]; | oldpos = add_off_t(oldpos, ctrl[2]); | ||||
} | } | ||||
/* Clean up the bzip2 reads */ | /* Clean up the bzip2 reads */ | ||||
BZ2_bzReadClose(&cbz2err, cpfbz2); | BZ2_bzReadClose(&cbz2err, cpfbz2); | ||||
BZ2_bzReadClose(&dbz2err, dpfbz2); | BZ2_bzReadClose(&dbz2err, dpfbz2); | ||||
BZ2_bzReadClose(&ebz2err, epfbz2); | BZ2_bzReadClose(&ebz2err, epfbz2); | ||||
if (fclose(cpf) || fclose(dpf) || fclose(epf)) | if (fclose(cpf) || fclose(dpf) || fclose(epf)) | ||||
err(1, "fclose(%s)", argv[3]); | err(1, "fclose(%s)", argv[3]); | ||||
Show All 12 Lines |
Maybe inline?