]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3373. [bug] win32: open raw files in binary mode. [RT #30944]
authorMark Andrews <marka@isc.org>
Wed, 12 Sep 2012 02:04:58 +0000 (12:04 +1000)
committerMark Andrews <marka@isc.org>
Wed, 12 Sep 2012 02:04:58 +0000 (12:04 +1000)
CHANGES
lib/dns/master.c
lib/dns/masterdump.c
lib/dns/rdata.c
lib/isc/api
lib/isc/include/isc/file.h
lib/isc/unix/file.c
lib/isc/win32/file.c
lib/isc/win32/libisc.def

diff --git a/CHANGES b/CHANGES
index b4d554692b556d583ba0c2516d690094b1db1a6b..ea7b9f5563343476f92757e8fd3822861033bbca 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,7 @@
        --- 9.6-ESV-R8 released ---
 
+3373.  [bug]           win32: open raw files in binary mode. [RT #30944]
+
 3364.  [security]      Named could die on specially crafted record.
                        [RT #30416]
 
index 84af3b83661458c5437b05e5de8d85ff3f4c4c58..d87d3987f3509c8a5dd887fc47c278b515b5e87a 100644 (file)
@@ -34,6 +34,7 @@
 #include <isc/util.h>
 
 #include <dns/callbacks.h>
+#include <dns/compress.h>
 #include <dns/events.h>
 #include <dns/fixedname.h>
 #include <dns/master.h>
@@ -2031,19 +2032,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;
@@ -2100,6 +2103,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
@@ -2111,7 +2117,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;
@@ -2201,12 +2207,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) {
@@ -2237,7 +2242,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,
@@ -2249,8 +2254,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;
 
@@ -2270,11 +2273,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);
                }
 
@@ -2291,7 +2303,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);
index 681304f589e7241a2be08220674f412c28871592..b02cc11f52199d765da0793e7eb82a72a4fe3874 100644 (file)
@@ -1483,7 +1483,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;
@@ -1498,7 +1499,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,
@@ -1542,7 +1546,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;
 
@@ -1596,7 +1600,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);
 
index 6f802623d7d1a10d3b22ffcd6280c4e22b9b8cc1..2577e6b29be2e90e3c38e42943e7c9d37395ed4f 100644 (file)
@@ -421,6 +421,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);
@@ -521,13 +523,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);
@@ -1152,7 +1152,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);
@@ -1326,7 +1327,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);
 }
index 7423d66f128bf46455029fdd98b63385fef5874e..e11f8735d1e66970e6d332810eef2ca6566c15ef 100644 (file)
@@ -3,6 +3,6 @@
 # 9.7: 60-79
 # 9.8: 80-89
 # 9.9: 90-109
-LIBINTERFACE = 57
-LIBREVISION = 4
-LIBAGE = 0
+LIBINTERFACE = 58
+LIBREVISION = 0
+LIBAGE = 1
index 56cf4f234af168a641aff8bf669003be91fda7ca..a7e65e4b03787ada4c469fde2768044337a9589c 100644 (file)
@@ -97,11 +97,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
index 943372e1619be2b7021396ba8af557ea42435bb6..582fc23df1790d3b3a9e98a470d98be0ceff40c0 100644 (file)
@@ -302,6 +302,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;
index 41edbb77239bf48562ffc43d322a1c9396fc59b3..cea11946f12d5df3e9277bdc99d57f7fea1b4a97 100644 (file)
  *
  */
 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++;
@@ -79,8 +83,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);
@@ -106,10 +109,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);
 }
 
 /*
@@ -163,7 +166,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);
@@ -298,7 +301,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
@@ -314,8 +317,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;
@@ -326,12 +329,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);
@@ -343,6 +351,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;
index 067bbd5db7a6c68821d61c20e527b61c46b3bf5a..ce3b38343af7dc42cb80ca3ebb40572784602e85 100644 (file)
@@ -110,6 +110,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