From: Mark Andrews Date: Wed, 12 Sep 2012 02:07:22 +0000 (+1000) Subject: 3373. [bug] win32: open raw files in binary mode. [RT #30944] X-Git-Tag: v9.7.7~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c69b1298092feb005cd5d176794a0992d130f76d;p=thirdparty%2Fbind9.git 3373. [bug] win32: open raw files in binary mode. [RT #30944] --- diff --git a/CHANGES b/CHANGES index 4635ffe8f43..589422846cc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,7 @@ --- 9.7.7 released --- +3373. [bug] win32: open raw files in binary mode. [RT #30944] + 3364. [security] Named could die on specially crafted record. [RT #30416] diff --git a/lib/dns/master.c b/lib/dns/master.c index 7f6cf581bf9..8304507f519 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -2076,19 +2076,21 @@ load_raw(dns_loadctx_t *lctx) { unsigned int loop_cnt = 0; dns_rdatacallbacks_t *callbacks; unsigned char namebuf[DNS_NAME_MAXWIRE]; - isc_region_t r; - dns_name_t name; + dns_fixedname_t fixed; + dns_name_t *name; rdatalist_head_t head, dummy; dns_rdatalist_t rdatalist; isc_mem_t *mctx = lctx->mctx; dns_rdata_t *rdata = NULL; unsigned int rdata_size = 0; int target_size = TSIZ; - isc_buffer_t target; + isc_buffer_t target, buf; unsigned char *target_mem = NULL; + dns_decompress_t dctx; REQUIRE(DNS_LCTX_VALID(lctx)); callbacks = lctx->callbacks; + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); if (lctx->first) { dns_masterrawheader_t header; @@ -2145,6 +2147,9 @@ load_raw(dns_loadctx_t *lctx) { } isc_buffer_init(&target, target_mem, target_size); + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + /* * In the following loop, we regard any error fatal regardless of * whether "MANYERRORS" is set in the context option. This is because @@ -2156,7 +2161,7 @@ load_raw(dns_loadctx_t *lctx) { for (loop_cnt = 0; (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt); loop_cnt++) { - unsigned int i, rdcount, consumed_name; + unsigned int i, rdcount; isc_uint16_t namelen; isc_uint32_t totallen; size_t minlen, readlen; @@ -2246,12 +2251,11 @@ load_raw(dns_loadctx_t *lctx) { lctx->f); if (result != ISC_R_SUCCESS) goto cleanup; + isc_buffer_setactive(&target, (unsigned int)namelen); - isc_buffer_activeregion(&target, &r); - dns_name_init(&name, NULL); - dns_name_fromregion(&name, &r); - isc_buffer_forward(&target, (unsigned int)namelen); - consumed_name = isc_buffer_consumedlength(&target); + result = dns_name_fromwire(name, &target, &dctx, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; /* Rdata contents. */ if (rdcount > rdata_size) { @@ -2282,7 +2286,7 @@ load_raw(dns_loadctx_t *lctx) { /* Partial Commit. */ ISC_LIST_APPEND(head, &rdatalist, link); - result = commit(callbacks, lctx, &head, &name, + result = commit(callbacks, lctx, &head, name, NULL, 0); for (j = 0; j < i; j++) { ISC_LIST_UNLINK(rdatalist.rdata, @@ -2294,8 +2298,6 @@ load_raw(dns_loadctx_t *lctx) { /* Rewind the buffer and continue */ isc_buffer_clear(&target); - isc_buffer_add(&target, consumed_name); - isc_buffer_forward(&target, consumed_name); rdcount -= i; @@ -2315,11 +2317,20 @@ load_raw(dns_loadctx_t *lctx) { if (result != ISC_R_SUCCESS) goto cleanup; isc_buffer_setactive(&target, (unsigned int)rdlen); - isc_buffer_activeregion(&target, &r); - isc_buffer_forward(&target, (unsigned int)rdlen); - dns_rdata_fromregion(&rdata[i], rdatalist.rdclass, - rdatalist.type, &r); - + /* + * It is safe to have the source active region and + * the target available region be the same if + * decompression is disabled (see dctx above) and we + * are not downcasing names (options == 0). + */ + isc_buffer_init(&buf, isc_buffer_current(&target), + (unsigned int)rdlen); + result = dns_rdata_fromwire(&rdata[i], + rdatalist.rdclass, + rdatalist.type, &target, + &dctx, 0, &buf); + if (result != ISC_R_SUCCESS) + goto cleanup; ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link); } @@ -2336,7 +2347,7 @@ load_raw(dns_loadctx_t *lctx) { ISC_LIST_APPEND(head, &rdatalist, link); /* Commit this RRset. rdatalist will be unlinked. */ - result = commit(callbacks, lctx, &head, &name, NULL, 0); + result = commit(callbacks, lctx, &head, name, NULL, 0); for (i = 0; i < rdcount; i++) { ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link); diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 0c17c1af235..a10e6f2d559 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -1545,7 +1545,8 @@ dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db, } static isc_result_t -opentmp(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) { +opentmp(isc_mem_t *mctx, dns_masterformat_t format, const char *file, + char **tempp, FILE **fp) { FILE *f = NULL; isc_result_t result; char *tempname = NULL; @@ -1560,7 +1561,10 @@ opentmp(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) { if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_file_openunique(tempname, &f); + if (format == dns_masterformat_text) + result = isc_file_openunique(tempname, &f); + else + result = isc_file_bopenunique(tempname, &f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, @@ -1604,7 +1608,7 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, if (file == NULL) return (ISC_R_NOMEMORY); - result = opentmp(mctx, filename, &tempname, &f); + result = opentmp(mctx, format, filename, &tempname, &f); if (result != ISC_R_SUCCESS) goto cleanup; @@ -1658,7 +1662,7 @@ dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, char *tempname; dns_dumpctx_t *dctx = NULL; - result = opentmp(mctx, filename, &tempname, &f); + result = opentmp(mctx, format, filename, &tempname, &f); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index f1259ab279c..2067b81a762 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -436,6 +436,8 @@ dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass, REQUIRE(DNS_RDATA_INITIALIZED(rdata)); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); } + REQUIRE(source != NULL); + REQUIRE(target != NULL); if (type == 0) return (DNS_R_FORMERR); @@ -536,13 +538,11 @@ rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass, dns_rdatatype_t type) { dns_decompress_t dctx; - dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); isc_buffer_setactive(src, isc_buffer_usedlength(src)); - result = dns_rdata_fromwire(&rdata, rdclass, type, src, - &dctx, 0, dest); + result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest); dns_decompress_invalidate(&dctx); return (result); @@ -1167,7 +1167,8 @@ txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { if (n > tregion.length) return (ISC_R_NOSPACE); - memcpy(tregion.base, sregion.base, n); + if (tregion.base != sregion.base) + memcpy(tregion.base, sregion.base, n); isc_buffer_forward(source, n); isc_buffer_add(target, n); return (ISC_R_SUCCESS); @@ -1341,7 +1342,8 @@ mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) { isc_buffer_availableregion(target, &tr); if (length > tr.length) return (ISC_R_NOSPACE); - memcpy(tr.base, base, length); + if (tr.base != base) + memcpy(tr.base, base, length); isc_buffer_add(target, length); return (ISC_R_SUCCESS); } diff --git a/lib/isc/api b/lib/isc/api index f029060e69a..52455ebc18c 100644 --- a/lib/isc/api +++ b/lib/isc/api @@ -3,6 +3,6 @@ # 9.7: 60-79 # 9.8: 80-89 # 9.9: 90-109 -LIBINTERFACE = 66 -LIBREVISION = 1 -LIBAGE = 1 +LIBINTERFACE = 67 +LIBREVISION = 0 +LIBAGE = 2 diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h index 22a8539ad6a..86576458694 100644 --- a/lib/isc/include/isc/file.h +++ b/lib/isc/include/isc/file.h @@ -101,11 +101,14 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen); * of the path with the internal template string. */ - isc_result_t isc_file_openunique(char *templet, FILE **fp); +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp); /*!< * \brief Create and open a file with a unique name based on 'templet'. + * isc_file_bopen*() open the file in binary mode in Windows. + * isc_file_open*() open the file in text mode in Windows. * * Notes: *\li 'template' is a reserved work in C++. If you want to complain diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c index aa40c477dcf..458885b5a8e 100644 --- a/lib/isc/unix/file.c +++ b/lib/isc/unix/file.c @@ -317,6 +317,11 @@ isc_file_openunique(char *templet, FILE **fp) { return (result); } +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp) { + return (isc_file_openunique(templet, fp)); +} + isc_result_t isc_file_remove(const char *filename) { int r; diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c index 4edd37d9fa2..64572a276d9 100644 --- a/lib/isc/win32/file.c +++ b/lib/isc/win32/file.c @@ -45,10 +45,14 @@ * */ static int -gettemp(char *path, int *doopen) { +gettemp(char *path, isc_boolean_t binary, int *doopen) { char *start, *trv; struct stat sbuf; int pid; + int flags = O_CREAT|O_EXCL|O_RDWR; + + if (binary) + flags |= O_BINARY; trv = strrchr(path, 'X'); trv++; @@ -81,8 +85,7 @@ gettemp(char *path, int *doopen) { for (;;) { if (doopen) { if ((*doopen = - open(path, O_CREAT|O_EXCL|O_RDWR, - _S_IREAD | _S_IWRITE)) >= 0) + open(path, flags, _S_IREAD | _S_IWRITE)) >= 0) return (1); if (errno != EEXIST) return (0); @@ -108,10 +111,10 @@ gettemp(char *path, int *doopen) { } static int -mkstemp(char *path) { +mkstemp(char *path, isc_boolean_t binary) { int fd; - return (gettemp(path, &fd) ? fd : -1); + return (gettemp(path, binary, &fd) ? fd : -1); } /* @@ -165,7 +168,7 @@ isc_file_safemovefile(const char *oldname, const char *newname) { exists = TRUE; strcpy(buf, newname); strcat(buf, ".XXXXX"); - tmpfd = mkstemp(buf); + tmpfd = mkstemp(buf, ISC_TRUE); if (tmpfd > 0) _close(tmpfd); DeleteFile(buf); @@ -300,7 +303,7 @@ isc_file_renameunique(const char *file, char *templet) { REQUIRE(file != NULL); REQUIRE(templet != NULL); - fd = mkstemp(templet); + fd = mkstemp(templet, ISC_TRUE); if (fd == -1) result = isc__errno2result(errno); else @@ -316,8 +319,8 @@ isc_file_renameunique(const char *file, char *templet) { return (result); } -isc_result_t -isc_file_openunique(char *templet, FILE **fp) { +static isc_result_t +openuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) { int fd; FILE *f; isc_result_t result = ISC_R_SUCCESS; @@ -328,12 +331,17 @@ isc_file_openunique(char *templet, FILE **fp) { /* * Win32 does not have mkstemp. Using emulation above. */ - fd = mkstemp(templet); + fd = mkstemp(templet, binary); if (fd == -1) result = isc__errno2result(errno); if (result == ISC_R_SUCCESS) { - f = fdopen(fd, "w+"); +#if 1 + UNUSED(mode); +#else + (void)fchmod(fd, mode); +#endif + f = fdopen(fd, binary ? "wb+", "w+"); if (f == NULL) { result = isc__errno2result(errno); (void)remove(templet); @@ -345,6 +353,18 @@ isc_file_openunique(char *templet, FILE **fp) { return (result); } +isc_result_t +isc_file_openunique(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, ISC_FALSE, fp)); +} + +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, ISC_TRUE, fp)); +} + isc_result_t isc_file_remove(const char *filename) { int r; diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def index 7aac5d7743e..32710dd26f3 100644 --- a/lib/isc/win32/libisc.def +++ b/lib/isc/win32/libisc.def @@ -212,6 +212,7 @@ isc_event_allocate isc_event_free isc_file_absolutepath isc_file_basename +isc_file_bopenunique isc_file_exists isc_file_getmodtime isc_file_isabsolute