]> 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 01:59:59 +0000 (11:59 +1000)
committerMark Andrews <marka@isc.org>
Wed, 12 Sep 2012 01:59:59 +0000 (11:59 +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 8a98f3647be708166069039370818a446a8b0533..f826b5ccebba4796a6a612f8284d962bae465ee2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,7 @@
        --- 9.9.2 released ---
 
+3373.  [bug]           win32: open raw files in binary mode. [RT #30944]
+
 3364.  [security]      Named could die on specially crafted record.
                        [RT #30416]
 
index 7b1ccdf8436c86c768e28d24fd29e38f21993a31..a8a456d7a355c8c59237b9e77e291a3c781bd680 100644 (file)
@@ -2078,20 +2078,22 @@ 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_masterrawheader_t header;
+       dns_decompress_t dctx;
 
        REQUIRE(DNS_LCTX_VALID(lctx));
        callbacks = lctx->callbacks;
+       dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
 
        dns_master_initrawheader(&header);
 
@@ -2171,6 +2173,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
@@ -2182,7 +2187,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;
@@ -2272,12 +2277,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) {
@@ -2308,7 +2312,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,
@@ -2320,8 +2324,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;
 
@@ -2341,11 +2343,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);
                }
 
@@ -2362,7 +2373,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 e800715e204b10ac484adbdd7f7cdbe895d7447c..2717658e691adbcbf46434fcb5ec588e02c67dd1 100644 (file)
@@ -1614,7 +1614,8 @@ dns_master_dumptostream3(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;
@@ -1629,7 +1630,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,
@@ -1684,7 +1688,7 @@ dns_master_dumpinc3(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;
 
@@ -1748,7 +1752,7 @@ dns_master_dump3(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 683130ac833b4c6ee54fca52a65a6e2b7b2b2326..b6e715eff0b1314977b9ce6c1db940ef36ac2b56 100644 (file)
@@ -445,6 +445,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);
@@ -545,13 +547,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);
@@ -1182,7 +1182,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);
@@ -1331,7 +1332,8 @@ multitxt_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);
                isc_buffer_activeregion(source, &sregion);
@@ -1507,7 +1509,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 ad36a1d3cb5b0187bedcfdfccc05fc75e9dd0e56..178430ae9b8ce81f980773ee56a425c5c53fabbc 100644 (file)
@@ -3,6 +3,6 @@
 # 9.7: 60-79
 # 9.8: 80-89
 # 9.9: 90-109
-LIBINTERFACE = 92
-LIBREVISION = 1
-LIBAGE = 0
+LIBINTERFACE = 93
+LIBREVISION = 0
+LIBAGE = 1
index f1972357ca85a96ed18cf1a2876fd004150603c6..38f78b7403e83f86f06177f952653e90e1d5643f 100644 (file)
@@ -101,15 +101,22 @@ 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_openuniqueprivate(char *templet, FILE **fp);
 isc_result_t
 isc_file_openuniquemode(char *templet, int mode, FILE **fp);
+isc_result_t
+isc_file_bopenunique(char *templet, FILE **fp);
+isc_result_t
+isc_file_bopenuniqueprivate(char *templet, FILE **fp);
+isc_result_t
+isc_file_bopenuniquemode(char *templet, int mode, 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 f8d22ab458b1a355df6d12bf3fdf734bbb5bba1d..99c02ec7b6283a9fdba905718ec83a5b8e394d50 100644 (file)
@@ -326,6 +326,23 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
        return (result);
 }
 
+isc_result_t
+isc_file_bopenunique(char *templet, FILE **fp) {
+       int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_bopenuniqueprivate(char *templet, FILE **fp) {
+       int mode = S_IWUSR|S_IRUSR;
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) {
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
 isc_result_t
 isc_file_remove(const char *filename) {
        int r;
index b86b201341c2eb61984efa50ac07a61f3a7691ec..74a7bcbfa5641b5e8bf955654dcdc11b80e31a6d 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,20 +319,8 @@ isc_file_renameunique(const char *file, char *templet) {
        return (result);
 }
 
-isc_result_t
-isc_file_openuniqueprivate(char *templet, FILE **fp) {
-       int mode = _S_IREAD | _S_IWRITE;
-       return (isc_file_openuniquemode(templet, mode, fp));
-}
-
-isc_result_t
-isc_file_openunique(char *templet, FILE **fp) {
-       int mode = _S_IREAD | _S_IWRITE;
-       return (isc_file_openuniquemode(templet, mode, fp));
-}
-
-isc_result_t
-isc_file_openuniquemode(char *templet, int mode, 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;
@@ -340,7 +331,7 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
        /*
         * Win32 does not have mkstemp. Using emulation above.
         */
-       fd = mkstemp(templet);
+       fd = mkstemp(templet, binary);
 
        if (fd == -1)
                result = isc__errno2result(errno);
@@ -350,7 +341,7 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
 #else
                (void)fchmod(fd, mode);
 #endif
-               f = fdopen(fd, "w+");
+               f = fdopen(fd, binary ? "wb+", "w+");
                if (f == NULL) {
                        result = isc__errno2result(errno);
                        (void)remove(templet);
@@ -362,6 +353,40 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
        return (result);
 }
 
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+       int mode = _S_IREAD | _S_IWRITE;
+       return (openuniquemode(templet, mode, ISC_FALSE, fp));
+}
+
+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_openuniquemode(char *templet, int mode, FILE **fp) {
+       return (openuniquemode(templet, mode, ISC_FALSE, fp));
+}
+
+isc_result_t
+isc_file_bopenuniqueprivate(char *templet, FILE **fp) {
+       int mode = _S_IREAD | _S_IWRITE;
+       return (openuniquemode(templet, mode, ISC_TRUE, 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_bopenuniquemode(char *templet, int mode, FILE **fp) {
+       return (openuniquemode(templet, mode, ISC_TRUE, fp));
+}
+
 isc_result_t
 isc_file_remove(const char *filename) {
        int r;
index fa5314d3a576aa4f6a0782fd8f34b81a010afbfa..fe3f739ba678c0f202aa57cf73469c8cc5d5a1ce 100644 (file)
@@ -220,6 +220,9 @@ isc_event_allocate
 isc_event_free
 isc_file_absolutepath
 isc_file_basename
+isc_file_bopenunique
+isc_file_bopenuniquemode
+isc_file_bopenuniqueprivate
 isc_file_exists
 isc_file_getmodtime
 isc_file_isabsolute