diff options
Diffstat (limited to 'sys/contrib/openzfs/cmd/zstream/zstream_redup.c')
-rw-r--r-- | sys/contrib/openzfs/cmd/zstream/zstream_redup.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_redup.c b/sys/contrib/openzfs/cmd/zstream/zstream_redup.c index 474527e76ea7..c56a09cee75d 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream_redup.c +++ b/sys/contrib/openzfs/cmd/zstream/zstream_redup.c @@ -27,7 +27,7 @@ #include <stddef.h> #include <stdio.h> #include <stdlib.h> -#include <strings.h> +#include <string.h> #include <umem.h> #include <unistd.h> #include <sys/debug.h> @@ -65,7 +65,7 @@ highbit64(uint64_t i) return (NBBY * sizeof (uint64_t) - __builtin_clzll(i)); } -static void * +void * safe_calloc(size_t n) { void *rv = calloc(1, n); @@ -81,7 +81,7 @@ safe_calloc(size_t n) /* * Safe version of fread(), exits on error. */ -static int +int sfread(void *buf, size_t size, FILE *fp) { int rv = fread(buf, size, 1, fp); @@ -222,6 +222,8 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) char *buf = safe_calloc(bufsz); FILE *ofp = fdopen(infd, "r"); long offset = ftell(ofp); + int begin = 0; + boolean_t seen = B_FALSE; while (sfread(drr, sizeof (*drr), ofp) != 0) { num_records++; @@ -229,7 +231,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) * We need to regenerate the checksum. */ if (drr->drr_type != DRR_BEGIN) { - bzero(&drr->drr_u.drr_checksum.drr_checksum, + memset(&drr->drr_u.drr_checksum.drr_checksum, 0, sizeof (drr->drr_u.drr_checksum.drr_checksum)); } @@ -240,6 +242,8 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) struct drr_begin *drrb = &drr->drr_u.drr_begin; int fflags; ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0); + VERIFY0(begin++); + seen = B_TRUE; assert(drrb->drr_magic == DMU_BACKUP_MAGIC); @@ -250,7 +254,10 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) /* cppcheck-suppress syntaxError */ DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags); - int sz = drr->drr_payloadlen; + uint32_t sz = drr->drr_payloadlen; + + VERIFY3U(sz, <=, 1U << 28); + if (sz != 0) { if (sz > bufsz) { free(buf); @@ -267,6 +274,13 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) { struct drr_end *drre = &drr->drr_u.drr_end; /* + * We would prefer to just check --begin == 0, but + * replication streams have an end of stream END + * record, so we must avoid tripping it. + */ + VERIFY3B(seen, ==, B_TRUE); + begin--; + /* * Use the recalculated checksum, unless this is * the END record of a stream package, which has * no checksum. @@ -279,6 +293,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) case DRR_OBJECT: { struct drr_object *drro = &drr->drr_u.drr_object; + VERIFY3S(begin, ==, 1); if (drro->drr_bonuslen > 0) { payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro); @@ -290,6 +305,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) case DRR_SPILL: { struct drr_spill *drrs = &drr->drr_u.drr_spill; + VERIFY3S(begin, ==, 1); payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs); (void) sfread(buf, payload_size, ofp); break; @@ -299,6 +315,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) { struct drr_write_byref drrwb = drr->drr_u.drr_write_byref; + VERIFY3S(begin, ==, 1); num_write_byref_records++; @@ -334,6 +351,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) case DRR_WRITE: { struct drr_write *drrw = &drr->drr_u.drr_write; + VERIFY3S(begin, ==, 1); payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw); (void) sfread(buf, payload_size, ofp); @@ -346,6 +364,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) { struct drr_write_embedded *drrwe = &drr->drr_u.drr_write_embedded; + VERIFY3S(begin, ==, 1); payload_size = P2ROUNDUP((uint64_t)drrwe->drr_psize, 8); (void) sfread(buf, payload_size, ofp); @@ -355,6 +374,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) case DRR_FREEOBJECTS: case DRR_FREE: case DRR_OBJECT_RANGE: + VERIFY3S(begin, ==, 1); break; default: @@ -380,7 +400,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose) * a checksum. */ if (drr->drr_type != DRR_BEGIN) { - bzero(&drr->drr_u.drr_checksum.drr_checksum, + memset(&drr->drr_u.drr_checksum.drr_checksum, 0, sizeof (drr->drr_u.drr_checksum.drr_checksum)); } if (dump_record(drr, buf, payload_size, |