From 5c33042498763ce814c0539e0a96f73a06a76dfd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 12 Sep 2009 15:21:33 +1000 Subject: [PATCH] s4-ndr: fixed memory leaks in ndr_pull_*_blob() We needed to free the ndr structures, both on error and normal return --- librpc/ndr/libndr.h | 10 ++++++++++ librpc/ndr/ndr.c | 25 ++++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h index 7b981f9171f..d01b68ef516 100644 --- a/librpc/ndr/libndr.h +++ b/librpc/ndr/libndr.h @@ -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 {\ diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index 837690b484f..2b3493b2e34 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -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; } -- 2.11.4.GIT