diff options
author | Andrew Bartlett <abartlet@samba.org> | 2016-06-17 13:29:51 +1200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2016-07-28 10:06:12 +0200 |
commit | 1246904d41eebc3440636dd29a9dc9ba38b738f6 (patch) | |
tree | 642617b02dd9318c0ed4d2b14e880aa4a902e83d /librpc/ndr | |
parent | c07504f40dea1b850aa84dab6af5216b097217cc (diff) | |
download | samba-1246904d41eebc3440636dd29a9dc9ba38b738f6.tar.gz |
librpc: Add ndr_push_struct_into_fixed_blob() and use it in GUID_to_ndr_blob()
This allows us to allocate only the correct size, not a default of 1024 bytes
per push.
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'librpc/ndr')
-rw-r--r-- | librpc/ndr/libndr.h | 6 | ||||
-rw-r--r-- | librpc/ndr/ndr.c | 40 | ||||
-rw-r--r-- | librpc/ndr/uuid.c | 8 |
3 files changed, 51 insertions, 3 deletions
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h index 6034229336e..0c3c55a9bf2 100644 --- a/librpc/ndr/libndr.h +++ b/librpc/ndr/libndr.h @@ -83,7 +83,8 @@ struct ndr_push { uint8_t *data; uint32_t alloc_size; uint32_t offset; - + bool fixed_buf_size; + uint32_t relative_base_offset; uint32_t relative_end_offset; struct ndr_token_list *relative_base_list; @@ -466,6 +467,9 @@ bool ndr_syntax_id_equal(const struct ndr_syntax_id *i1, const struct ndr_syntax char *ndr_syntax_id_to_string(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *id); bool ndr_syntax_id_from_string(const char *s, struct ndr_syntax_id *id); enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, ndr_push_flags_fn_t fn); +enum ndr_err_code ndr_push_struct_into_fixed_blob(DATA_BLOB *blob, + const void *p, + ndr_push_flags_fn_t fn); enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_push_flags_fn_t fn); size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push); size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push); diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index 78cde20f7d1..22c4d763d09 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -254,6 +254,17 @@ _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_ size); } + if (ndr->fixed_buf_size) { + if (ndr->alloc_size >= size) { + return NDR_ERR_SUCCESS; + } + return ndr_push_error(ndr, + NDR_ERR_BUFSIZE, + "Overflow of fixed buffer in " + "push_expand to %u", + size); + } + if (ndr->alloc_size > size) { return NDR_ERR_SUCCESS; } @@ -1264,6 +1275,35 @@ _PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem return NDR_ERR_SUCCESS; } +/* + push a struct into a provided blob using NDR. + + We error because we want to have the performance issue (extra + talloc() calls) show up as an error, not just slower code. This is + used for things like GUIDs, which we expect to be a fixed size, and + SIDs that we can pre-calculate the size for. +*/ +_PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob( + DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn) +{ + struct ndr_push ndr = { + .data = blob->data, + .alloc_size = blob->length, + .fixed_buf_size = true + }; + + NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p)); + + if (ndr.offset != blob->length) { + return ndr_push_error(&ndr, NDR_ERR_BUFSIZE, + "buffer was either to large or small " + "ofs[%u] size[%zu]", + ndr.offset, blob->length); + } + + return NDR_ERR_SUCCESS; +} + /* push a union to a blob using NDR */ diff --git a/librpc/ndr/uuid.c b/librpc/ndr/uuid.c index fbd305e5401..a3f68d1d344 100644 --- a/librpc/ndr/uuid.c +++ b/librpc/ndr/uuid.c @@ -31,8 +31,12 @@ _PUBLIC_ NTSTATUS GUID_to_ndr_blob(const struct GUID *guid, TALLOC_CTX *mem_ctx, DATA_BLOB *b) { enum ndr_err_code ndr_err; - ndr_err = ndr_push_struct_blob(b, mem_ctx, guid, - (ndr_push_flags_fn_t)ndr_push_GUID); + *b = data_blob_talloc(mem_ctx, NULL, 16); + if (b->data == NULL) { + return NT_STATUS_NO_MEMORY; + } + ndr_err = ndr_push_struct_into_fixed_blob( + b, guid, (ndr_push_flags_fn_t)ndr_push_GUID); return ndr_map_error2ntstatus(ndr_err); } |