s4-ndr: fixed memory leaks in ndr_pull_*_blob()
authorAndrew Tridgell <tridge@samba.org>
Sat, 12 Sep 2009 05:21:33 +0000 (15:21 +1000)
committerAndrew Tridgell <tridge@samba.org>
Sat, 12 Sep 2009 05:21:33 +0000 (15:21 +1000)
We needed to free the ndr structures, both on error and normal return

librpc/ndr/libndr.h
librpc/ndr/ndr.c

index 7b981f9171fcfff7d80b7e4bf9301740c7bf47fa..d01b68ef5160f577753006f7c2b403fbd7c80ed0 100644 (file)
@@ -254,6 +254,16 @@ enum ndr_compression_alg {
        } \
 } while (0)
 
+/* if the call fails then free the ndr pointer */
+#define NDR_CHECK_FREE(call) do { \
+       enum ndr_err_code _status; \
+       _status = call; \
+       if (!NDR_ERR_CODE_IS_SUCCESS(_status)) { \
+               talloc_free(ndr);                \
+               return _status; \
+       } \
+} while (0)
+
 #define NDR_PULL_GET_MEM_CTX(ndr) (ndr->current_mem_ctx)
 
 #define NDR_PULL_SET_MEM_CTX(ndr, mem_ctx, flgs) do {\
index 837690b484f9bd1a7c08c79c983a9e80a9916b1c..2b3493b2e3423ffc66ea4bb42fc686a7685c7a65 100644 (file)
@@ -846,7 +846,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CT
        struct ndr_pull *ndr;
        ndr = ndr_pull_init_blob(blob, mem_ctx, iconv_convenience);
        NDR_ERR_HAVE_NO_MEMORY(ndr);
-       NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+       NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+       talloc_free(ndr);
        return NDR_ERR_SUCCESS;
 }
 
@@ -860,12 +861,13 @@ _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLO
        struct ndr_pull *ndr;
        ndr = ndr_pull_init_blob(blob, mem_ctx, iconv_convenience);
        NDR_ERR_HAVE_NO_MEMORY(ndr);
-       NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+       NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
        if (ndr->offset < ndr->data_size) {
                return ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
                                      "not all bytes consumed ofs[%u] size[%u]",
                                      ndr->offset, ndr->data_size);
        }
+       talloc_free(ndr);
        return NDR_ERR_SUCCESS;
 }
 
@@ -879,8 +881,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX
        struct ndr_pull *ndr;
        ndr = ndr_pull_init_blob(blob, mem_ctx, iconv_convenience);
        NDR_ERR_HAVE_NO_MEMORY(ndr);
-       NDR_CHECK(ndr_pull_set_switch_value(ndr, p, level));
-       NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+       NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
+       NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+       talloc_free(ndr);
        return NDR_ERR_SUCCESS;
 }
 
@@ -895,13 +898,17 @@ _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC
        struct ndr_pull *ndr;
        ndr = ndr_pull_init_blob(blob, mem_ctx, iconv_convenience);
        NDR_ERR_HAVE_NO_MEMORY(ndr);
-       NDR_CHECK(ndr_pull_set_switch_value(ndr, p, level));
-       NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+       NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
+       NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
        if (ndr->offset < ndr->data_size) {
-               return ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
-                                     "not all bytes consumed ofs[%u] size[%u]",
-                                     ndr->offset, ndr->data_size);
+               enum ndr_err_code ret;
+               ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
+                                    "not all bytes consumed ofs[%u] size[%u]",
+                                    ndr->offset, ndr->data_size);
+               talloc_free(ndr);
+               return ret;
        }
+       talloc_free(ndr);
        return NDR_ERR_SUCCESS;
 }