]> 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:07:22 +0000 (12:07 +1000)
committerMark Andrews <marka@isc.org>
Wed, 12 Sep 2012 02:07:22 +0000 (12:07 +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 4635ffe8f435c7e08b6af0b611ad699bb5162740..589422846cc8b67ef7eae8413164854395684c54 100644 (file)
--- 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]
 
index 7f6cf581bf953b86df2243701d65624864fabddb..8304507f519333010cdb69bd4cc80d3ea216327c 100644 (file)
@@ -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);
index 0c17c1af235d7cb7105e68f0c943dc50e6a8bc78..a10e6f2d559ecab5a268fe5c42d0583b35a88ccd 100644 (file)
@@ -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);
 
index f1259ab279c7c3187f77e22b861f3b2fbdb125ea..2067b81a762c93373bd81d9b0c24e7e02eeef5ca 100644 (file)
@@ -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);
 }
index f029060e69ac0e0250b80427e92b9a1489490998..52455ebc18c3c406dc60b55f033656235efd26ad 100644 (file)
@@ -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
index 22a8539ad6a1089e27b21134d4465d572cb5b8b9..8657645869435faba7ea6ad0044b078c150c089f 100644 (file)
@@ -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
index aa40c477dcf6fe551162b2115e0a1602472a0efd..458885b5a8ef92f9f7dde6d4b42f26faba1d7ccd 100644 (file)
@@ -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;
index 4edd37d9fa205b2b81423438b47fd78d32cc9dbe..64572a276d991953a992800ce5d08e111fd24cf1 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++;
@@ -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;
index 7aac5d7743e7258fcbcf113862baaa894ac213b4..32710dd26f3a03b3f69c68a660665122d7d33c5c 100644 (file)
@@ -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