From fc45c59937b9e3196f582208cfb54da39502febd Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 26 Feb 2016 17:01:37 +1300 Subject: [PATCH 1/5] ndr: avoid unnecessary searches of token list When pulling complex structures like nt-acls, a long list of tokens may be produced. This change means the token list won't be walked in the buffers case if the switch value is not needed. Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam --- pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 49 +++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index f52d4b1..c53ec4a 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -321,6 +321,25 @@ sub check_null_pointer($$$$) } } +sub is_deferred_switch_non_empty($) +{ + # 1 if there needs to be a deferred branch in an ndr_pull/push, + # 0 otherwise. + my ($e) = @_; + my $have_default = 0; + foreach my $el (@{$e->{ELEMENTS}}) { + if ($el->{CASE} eq "default") { + $have_default = 1; + } + if ($el->{TYPE} ne "EMPTY") { + if (ContainsDeferred($el, $el->{LEVELS}[0])) { + return 1; + } + } + } + return ! $have_default; +} + sub ParseArrayPullGetSize($$$$$$) { my ($self,$e,$l,$ndr,$var_name,$env) = @_; @@ -1923,11 +1942,13 @@ sub ParseUnionPush($$$$) $self->ParseUnionPushPrimitives($e, $ndr, $varname); $self->deindent; $self->pidl("}"); - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->ParseUnionPushDeferred($e, $ndr, $varname); - $self->deindent; - $self->pidl("}"); + if (is_deferred_switch_non_empty($e)) { + $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); + $self->indent; + $self->ParseUnionPushDeferred($e, $ndr, $varname); + $self->deindent; + $self->pidl("}"); + } $self->end_flags($e, $ndr); } @@ -2093,21 +2114,21 @@ sub ParseUnionPull($$$$) $self->start_flags($e, $ndr); - $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); - $self->pidl("NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);"); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; + $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); $self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type); $self->deindent; $self->pidl("}"); - - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->ParseUnionPullDeferred($e,$ndr,$varname); - $self->deindent; - $self->pidl("}"); - + if (is_deferred_switch_non_empty($e)) { + $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); + $self->indent; + $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); + $self->ParseUnionPullDeferred($e,$ndr,$varname); + $self->deindent; + $self->pidl("}"); + } $self->add_deferred(); $self->end_flags($e, $ndr); -- 1.9.1 From 3213bb52fada3eaed90cda558826896fb32a95db Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 1 Mar 2016 12:26:33 +1300 Subject: [PATCH 2/5] librpc ndr: add ndr_pull_steal_switch_value() Switch values currently only have a peek variant, instead of a retrieve variant for getting their values. This can create performance issues with complex structures as the token list simply grows longer. Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam --- librpc/ABI/ndr-0.0.6.sigs | 256 ++++++++++++++++++++++++++++++++++++++++++++++ librpc/ndr/libndr.h | 1 + librpc/ndr/ndr.c | 14 +++ librpc/wscript_build | 2 +- 4 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 librpc/ABI/ndr-0.0.6.sigs diff --git a/librpc/ABI/ndr-0.0.6.sigs b/librpc/ABI/ndr-0.0.6.sigs new file mode 100644 index 0000000..a9b27a3 --- /dev/null +++ b/librpc/ABI/ndr-0.0.6.sigs @@ -0,0 +1,256 @@ +GUID_all_zero: bool (const struct GUID *) +GUID_buf_string: char *(const struct GUID *, struct GUID_txt_buf *) +GUID_compare: int (const struct GUID *, const struct GUID *) +GUID_equal: bool (const struct GUID *, const struct GUID *) +GUID_from_data_blob: NTSTATUS (const DATA_BLOB *, struct GUID *) +GUID_from_ndr_blob: NTSTATUS (const DATA_BLOB *, struct GUID *) +GUID_from_string: NTSTATUS (const char *, struct GUID *) +GUID_hexstring: char *(TALLOC_CTX *, const struct GUID *) +GUID_random: struct GUID (void) +GUID_string: char *(TALLOC_CTX *, const struct GUID *) +GUID_string2: char *(TALLOC_CTX *, const struct GUID *) +GUID_to_ndr_blob: NTSTATUS (const struct GUID *, TALLOC_CTX *, DATA_BLOB *) +GUID_zero: struct GUID (void) +ndr_align_size: size_t (uint32_t, size_t) +ndr_charset_length: uint32_t (const void *, charset_t) +ndr_check_array_length: enum ndr_err_code (struct ndr_pull *, void *, uint32_t) +ndr_check_array_size: enum ndr_err_code (struct ndr_pull *, void *, uint32_t) +ndr_check_padding: void (struct ndr_pull *, size_t) +ndr_check_pipe_chunk_trailer: enum ndr_err_code (struct ndr_pull *, int, uint32_t) +ndr_check_string_terminator: enum ndr_err_code (struct ndr_pull *, uint32_t, uint32_t) +ndr_get_array_length: uint32_t (struct ndr_pull *, const void *) +ndr_get_array_size: uint32_t (struct ndr_pull *, const void *) +ndr_map_error2errno: int (enum ndr_err_code) +ndr_map_error2ntstatus: NTSTATUS (enum ndr_err_code) +ndr_map_error2string: const char *(enum ndr_err_code) +ndr_policy_handle_empty: bool (const struct policy_handle *) +ndr_policy_handle_equal: bool (const struct policy_handle *, const struct policy_handle *) +ndr_print_DATA_BLOB: void (struct ndr_print *, const char *, DATA_BLOB) +ndr_print_GUID: void (struct ndr_print *, const char *, const struct GUID *) +ndr_print_HRESULT: void (struct ndr_print *, const char *, HRESULT) +ndr_print_KRB5_EDATA_NTSTATUS: void (struct ndr_print *, const char *, const struct KRB5_EDATA_NTSTATUS *) +ndr_print_NTSTATUS: void (struct ndr_print *, const char *, NTSTATUS) +ndr_print_NTTIME: void (struct ndr_print *, const char *, NTTIME) +ndr_print_NTTIME_1sec: void (struct ndr_print *, const char *, NTTIME) +ndr_print_NTTIME_hyper: void (struct ndr_print *, const char *, NTTIME) +ndr_print_WERROR: void (struct ndr_print *, const char *, WERROR) +ndr_print_array_uint8: void (struct ndr_print *, const char *, const uint8_t *, uint32_t) +ndr_print_bad_level: void (struct ndr_print *, const char *, uint16_t) +ndr_print_bitmap_flag: void (struct ndr_print *, size_t, const char *, uint32_t, uint32_t) +ndr_print_bool: void (struct ndr_print *, const char *, const bool) +ndr_print_debug: void (ndr_print_fn_t, const char *, void *) +ndr_print_debug_helper: void (struct ndr_print *, const char *, ...) +ndr_print_debugc: void (int, ndr_print_fn_t, const char *, void *) +ndr_print_debugc_helper: void (struct ndr_print *, const char *, ...) +ndr_print_dlong: void (struct ndr_print *, const char *, int64_t) +ndr_print_double: void (struct ndr_print *, const char *, double) +ndr_print_enum: void (struct ndr_print *, const char *, const char *, const char *, uint32_t) +ndr_print_function_debug: void (ndr_print_function_t, const char *, int, void *) +ndr_print_function_string: char *(TALLOC_CTX *, ndr_print_function_t, const char *, int, void *) +ndr_print_get_switch_value: uint32_t (struct ndr_print *, const void *) +ndr_print_gid_t: void (struct ndr_print *, const char *, gid_t) +ndr_print_hyper: void (struct ndr_print *, const char *, uint64_t) +ndr_print_int16: void (struct ndr_print *, const char *, int16_t) +ndr_print_int32: void (struct ndr_print *, const char *, int32_t) +ndr_print_int3264: void (struct ndr_print *, const char *, int32_t) +ndr_print_int8: void (struct ndr_print *, const char *, int8_t) +ndr_print_ipv4address: void (struct ndr_print *, const char *, const char *) +ndr_print_ipv6address: void (struct ndr_print *, const char *, const char *) +ndr_print_ndr_syntax_id: void (struct ndr_print *, const char *, const struct ndr_syntax_id *) +ndr_print_netr_SamDatabaseID: void (struct ndr_print *, const char *, enum netr_SamDatabaseID) +ndr_print_netr_SchannelType: void (struct ndr_print *, const char *, enum netr_SchannelType) +ndr_print_null: void (struct ndr_print *) +ndr_print_pointer: void (struct ndr_print *, const char *, void *) +ndr_print_policy_handle: void (struct ndr_print *, const char *, const struct policy_handle *) +ndr_print_printf_helper: void (struct ndr_print *, const char *, ...) +ndr_print_ptr: void (struct ndr_print *, const char *, const void *) +ndr_print_set_switch_value: enum ndr_err_code (struct ndr_print *, const void *, uint32_t) +ndr_print_sockaddr_storage: void (struct ndr_print *, const char *, const struct sockaddr_storage *) +ndr_print_string: void (struct ndr_print *, const char *, const char *) +ndr_print_string_array: void (struct ndr_print *, const char *, const char **) +ndr_print_string_helper: void (struct ndr_print *, const char *, ...) +ndr_print_struct: void (struct ndr_print *, const char *, const char *) +ndr_print_struct_string: char *(TALLOC_CTX *, ndr_print_fn_t, const char *, void *) +ndr_print_svcctl_ServerType: void (struct ndr_print *, const char *, uint32_t) +ndr_print_time_t: void (struct ndr_print *, const char *, time_t) +ndr_print_timespec: void (struct ndr_print *, const char *, const struct timespec *) +ndr_print_timeval: void (struct ndr_print *, const char *, const struct timeval *) +ndr_print_udlong: void (struct ndr_print *, const char *, uint64_t) +ndr_print_udlongr: void (struct ndr_print *, const char *, uint64_t) +ndr_print_uid_t: void (struct ndr_print *, const char *, uid_t) +ndr_print_uint16: void (struct ndr_print *, const char *, uint16_t) +ndr_print_uint32: void (struct ndr_print *, const char *, uint32_t) +ndr_print_uint3264: void (struct ndr_print *, const char *, uint32_t) +ndr_print_uint8: void (struct ndr_print *, const char *, uint8_t) +ndr_print_union: void (struct ndr_print *, const char *, int, const char *) +ndr_print_union_debug: void (ndr_print_fn_t, const char *, uint32_t, void *) +ndr_print_union_string: char *(TALLOC_CTX *, ndr_print_fn_t, const char *, uint32_t, void *) +ndr_print_winreg_Data: void (struct ndr_print *, const char *, const union winreg_Data *) +ndr_print_winreg_Type: void (struct ndr_print *, const char *, enum winreg_Type) +ndr_pull_DATA_BLOB: enum ndr_err_code (struct ndr_pull *, int, DATA_BLOB *) +ndr_pull_GUID: enum ndr_err_code (struct ndr_pull *, int, struct GUID *) +ndr_pull_HRESULT: enum ndr_err_code (struct ndr_pull *, int, HRESULT *) +ndr_pull_KRB5_EDATA_NTSTATUS: enum ndr_err_code (struct ndr_pull *, int, struct KRB5_EDATA_NTSTATUS *) +ndr_pull_NTSTATUS: enum ndr_err_code (struct ndr_pull *, int, NTSTATUS *) +ndr_pull_NTTIME: enum ndr_err_code (struct ndr_pull *, int, NTTIME *) +ndr_pull_NTTIME_1sec: enum ndr_err_code (struct ndr_pull *, int, NTTIME *) +ndr_pull_NTTIME_hyper: enum ndr_err_code (struct ndr_pull *, int, NTTIME *) +ndr_pull_WERROR: enum ndr_err_code (struct ndr_pull *, int, WERROR *) +ndr_pull_advance: enum ndr_err_code (struct ndr_pull *, uint32_t) +ndr_pull_align: enum ndr_err_code (struct ndr_pull *, size_t) +ndr_pull_append: enum ndr_err_code (struct ndr_pull *, DATA_BLOB *) +ndr_pull_array_length: enum ndr_err_code (struct ndr_pull *, const void *) +ndr_pull_array_size: enum ndr_err_code (struct ndr_pull *, const void *) +ndr_pull_array_uint8: enum ndr_err_code (struct ndr_pull *, int, uint8_t *, uint32_t) +ndr_pull_bytes: enum ndr_err_code (struct ndr_pull *, uint8_t *, uint32_t) +ndr_pull_charset: enum ndr_err_code (struct ndr_pull *, int, const char **, uint32_t, uint8_t, charset_t) +ndr_pull_charset_to_null: enum ndr_err_code (struct ndr_pull *, int, const char **, uint32_t, uint8_t, charset_t) +ndr_pull_dlong: enum ndr_err_code (struct ndr_pull *, int, int64_t *) +ndr_pull_double: enum ndr_err_code (struct ndr_pull *, int, double *) +ndr_pull_enum_uint16: enum ndr_err_code (struct ndr_pull *, int, uint16_t *) +ndr_pull_enum_uint1632: enum ndr_err_code (struct ndr_pull *, int, uint16_t *) +ndr_pull_enum_uint32: enum ndr_err_code (struct ndr_pull *, int, uint32_t *) +ndr_pull_enum_uint8: enum ndr_err_code (struct ndr_pull *, int, uint8_t *) +ndr_pull_error: enum ndr_err_code (struct ndr_pull *, enum ndr_err_code, const char *, ...) +ndr_pull_generic_ptr: enum ndr_err_code (struct ndr_pull *, uint32_t *) +ndr_pull_get_relative_base_offset: uint32_t (struct ndr_pull *) +ndr_pull_get_switch_value: uint32_t (struct ndr_pull *, const void *) +ndr_pull_gid_t: enum ndr_err_code (struct ndr_pull *, int, gid_t *) +ndr_pull_hyper: enum ndr_err_code (struct ndr_pull *, int, uint64_t *) +ndr_pull_init_blob: struct ndr_pull *(const DATA_BLOB *, TALLOC_CTX *) +ndr_pull_int16: enum ndr_err_code (struct ndr_pull *, int, int16_t *) +ndr_pull_int32: enum ndr_err_code (struct ndr_pull *, int, int32_t *) +ndr_pull_int8: enum ndr_err_code (struct ndr_pull *, int, int8_t *) +ndr_pull_ipv4address: enum ndr_err_code (struct ndr_pull *, int, const char **) +ndr_pull_ipv6address: enum ndr_err_code (struct ndr_pull *, int, const char **) +ndr_pull_ndr_syntax_id: enum ndr_err_code (struct ndr_pull *, int, struct ndr_syntax_id *) +ndr_pull_netr_SamDatabaseID: enum ndr_err_code (struct ndr_pull *, int, enum netr_SamDatabaseID *) +ndr_pull_netr_SchannelType: enum ndr_err_code (struct ndr_pull *, int, enum netr_SchannelType *) +ndr_pull_pointer: enum ndr_err_code (struct ndr_pull *, int, void **) +ndr_pull_policy_handle: enum ndr_err_code (struct ndr_pull *, int, struct policy_handle *) +ndr_pull_pop: enum ndr_err_code (struct ndr_pull *) +ndr_pull_ref_ptr: enum ndr_err_code (struct ndr_pull *, uint32_t *) +ndr_pull_relative_ptr1: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t) +ndr_pull_relative_ptr2: enum ndr_err_code (struct ndr_pull *, const void *) +ndr_pull_relative_ptr_short: enum ndr_err_code (struct ndr_pull *, uint16_t *) +ndr_pull_restore_relative_base_offset: void (struct ndr_pull *, uint32_t) +ndr_pull_set_switch_value: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t) +ndr_pull_setup_relative_base_offset1: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t) +ndr_pull_setup_relative_base_offset2: enum ndr_err_code (struct ndr_pull *, const void *) +ndr_pull_steal_switch_value: uint32_t (struct ndr_pull *, const void *) +ndr_pull_string: enum ndr_err_code (struct ndr_pull *, int, const char **) +ndr_pull_string_array: enum ndr_err_code (struct ndr_pull *, int, const char ***) +ndr_pull_struct_blob: enum ndr_err_code (const DATA_BLOB *, TALLOC_CTX *, void *, ndr_pull_flags_fn_t) +ndr_pull_struct_blob_all: enum ndr_err_code (const DATA_BLOB *, TALLOC_CTX *, void *, ndr_pull_flags_fn_t) +ndr_pull_subcontext_end: enum ndr_err_code (struct ndr_pull *, struct ndr_pull *, size_t, ssize_t) +ndr_pull_subcontext_start: enum ndr_err_code (struct ndr_pull *, struct ndr_pull **, size_t, ssize_t) +ndr_pull_svcctl_ServerType: enum ndr_err_code (struct ndr_pull *, int, uint32_t *) +ndr_pull_time_t: enum ndr_err_code (struct ndr_pull *, int, time_t *) +ndr_pull_timespec: enum ndr_err_code (struct ndr_pull *, int, struct timespec *) +ndr_pull_timeval: enum ndr_err_code (struct ndr_pull *, int, struct timeval *) +ndr_pull_trailer_align: enum ndr_err_code (struct ndr_pull *, size_t) +ndr_pull_udlong: enum ndr_err_code (struct ndr_pull *, int, uint64_t *) +ndr_pull_udlongr: enum ndr_err_code (struct ndr_pull *, int, uint64_t *) +ndr_pull_uid_t: enum ndr_err_code (struct ndr_pull *, int, uid_t *) +ndr_pull_uint16: enum ndr_err_code (struct ndr_pull *, int, uint16_t *) +ndr_pull_uint1632: enum ndr_err_code (struct ndr_pull *, int, uint16_t *) +ndr_pull_uint32: enum ndr_err_code (struct ndr_pull *, int, uint32_t *) +ndr_pull_uint3264: enum ndr_err_code (struct ndr_pull *, int, uint32_t *) +ndr_pull_uint8: enum ndr_err_code (struct ndr_pull *, int, uint8_t *) +ndr_pull_union_align: enum ndr_err_code (struct ndr_pull *, size_t) +ndr_pull_union_blob: enum ndr_err_code (const DATA_BLOB *, TALLOC_CTX *, void *, uint32_t, ndr_pull_flags_fn_t) +ndr_pull_union_blob_all: enum ndr_err_code (const DATA_BLOB *, TALLOC_CTX *, void *, uint32_t, ndr_pull_flags_fn_t) +ndr_pull_winreg_Data: enum ndr_err_code (struct ndr_pull *, int, union winreg_Data *) +ndr_pull_winreg_Type: enum ndr_err_code (struct ndr_pull *, int, enum winreg_Type *) +ndr_push_DATA_BLOB: enum ndr_err_code (struct ndr_push *, int, DATA_BLOB) +ndr_push_GUID: enum ndr_err_code (struct ndr_push *, int, const struct GUID *) +ndr_push_HRESULT: enum ndr_err_code (struct ndr_push *, int, HRESULT) +ndr_push_KRB5_EDATA_NTSTATUS: enum ndr_err_code (struct ndr_push *, int, const struct KRB5_EDATA_NTSTATUS *) +ndr_push_NTSTATUS: enum ndr_err_code (struct ndr_push *, int, NTSTATUS) +ndr_push_NTTIME: enum ndr_err_code (struct ndr_push *, int, NTTIME) +ndr_push_NTTIME_1sec: enum ndr_err_code (struct ndr_push *, int, NTTIME) +ndr_push_NTTIME_hyper: enum ndr_err_code (struct ndr_push *, int, NTTIME) +ndr_push_WERROR: enum ndr_err_code (struct ndr_push *, int, WERROR) +ndr_push_align: enum ndr_err_code (struct ndr_push *, size_t) +ndr_push_array_uint8: enum ndr_err_code (struct ndr_push *, int, const uint8_t *, uint32_t) +ndr_push_blob: DATA_BLOB (struct ndr_push *) +ndr_push_bytes: enum ndr_err_code (struct ndr_push *, const uint8_t *, uint32_t) +ndr_push_charset: enum ndr_err_code (struct ndr_push *, int, const char *, uint32_t, uint8_t, charset_t) +ndr_push_dlong: enum ndr_err_code (struct ndr_push *, int, int64_t) +ndr_push_double: enum ndr_err_code (struct ndr_push *, int, double) +ndr_push_enum_uint16: enum ndr_err_code (struct ndr_push *, int, uint16_t) +ndr_push_enum_uint1632: enum ndr_err_code (struct ndr_push *, int, uint16_t) +ndr_push_enum_uint32: enum ndr_err_code (struct ndr_push *, int, uint32_t) +ndr_push_enum_uint8: enum ndr_err_code (struct ndr_push *, int, uint8_t) +ndr_push_error: enum ndr_err_code (struct ndr_push *, enum ndr_err_code, const char *, ...) +ndr_push_expand: enum ndr_err_code (struct ndr_push *, uint32_t) +ndr_push_full_ptr: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_get_relative_base_offset: uint32_t (struct ndr_push *) +ndr_push_get_switch_value: uint32_t (struct ndr_push *, const void *) +ndr_push_gid_t: enum ndr_err_code (struct ndr_push *, int, gid_t) +ndr_push_hyper: enum ndr_err_code (struct ndr_push *, int, uint64_t) +ndr_push_init_ctx: struct ndr_push *(TALLOC_CTX *) +ndr_push_int16: enum ndr_err_code (struct ndr_push *, int, int16_t) +ndr_push_int32: enum ndr_err_code (struct ndr_push *, int, int32_t) +ndr_push_int8: enum ndr_err_code (struct ndr_push *, int, int8_t) +ndr_push_ipv4address: enum ndr_err_code (struct ndr_push *, int, const char *) +ndr_push_ipv6address: enum ndr_err_code (struct ndr_push *, int, const char *) +ndr_push_ndr_syntax_id: enum ndr_err_code (struct ndr_push *, int, const struct ndr_syntax_id *) +ndr_push_netr_SamDatabaseID: enum ndr_err_code (struct ndr_push *, int, enum netr_SamDatabaseID) +ndr_push_netr_SchannelType: enum ndr_err_code (struct ndr_push *, int, enum netr_SchannelType) +ndr_push_pipe_chunk_trailer: enum ndr_err_code (struct ndr_push *, int, uint32_t) +ndr_push_pointer: enum ndr_err_code (struct ndr_push *, int, void *) +ndr_push_policy_handle: enum ndr_err_code (struct ndr_push *, int, const struct policy_handle *) +ndr_push_ref_ptr: enum ndr_err_code (struct ndr_push *) +ndr_push_relative_ptr1: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_relative_ptr2_end: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_relative_ptr2_start: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_restore_relative_base_offset: void (struct ndr_push *, uint32_t) +ndr_push_set_switch_value: enum ndr_err_code (struct ndr_push *, const void *, uint32_t) +ndr_push_setup_relative_base_offset1: enum ndr_err_code (struct ndr_push *, const void *, uint32_t) +ndr_push_setup_relative_base_offset2: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_short_relative_ptr1: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_short_relative_ptr2: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_string: enum ndr_err_code (struct ndr_push *, int, const char *) +ndr_push_string_array: enum ndr_err_code (struct ndr_push *, int, const char **) +ndr_push_struct_blob: enum ndr_err_code (DATA_BLOB *, TALLOC_CTX *, const void *, ndr_push_flags_fn_t) +ndr_push_subcontext_end: enum ndr_err_code (struct ndr_push *, struct ndr_push *, size_t, ssize_t) +ndr_push_subcontext_start: enum ndr_err_code (struct ndr_push *, struct ndr_push **, size_t, ssize_t) +ndr_push_svcctl_ServerType: enum ndr_err_code (struct ndr_push *, int, uint32_t) +ndr_push_time_t: enum ndr_err_code (struct ndr_push *, int, time_t) +ndr_push_timespec: enum ndr_err_code (struct ndr_push *, int, const struct timespec *) +ndr_push_timeval: enum ndr_err_code (struct ndr_push *, int, const struct timeval *) +ndr_push_trailer_align: enum ndr_err_code (struct ndr_push *, size_t) +ndr_push_udlong: enum ndr_err_code (struct ndr_push *, int, uint64_t) +ndr_push_udlongr: enum ndr_err_code (struct ndr_push *, int, uint64_t) +ndr_push_uid_t: enum ndr_err_code (struct ndr_push *, int, uid_t) +ndr_push_uint16: enum ndr_err_code (struct ndr_push *, int, uint16_t) +ndr_push_uint1632: enum ndr_err_code (struct ndr_push *, int, uint16_t) +ndr_push_uint32: enum ndr_err_code (struct ndr_push *, int, uint32_t) +ndr_push_uint3264: enum ndr_err_code (struct ndr_push *, int, uint32_t) +ndr_push_uint8: enum ndr_err_code (struct ndr_push *, int, uint8_t) +ndr_push_union_align: enum ndr_err_code (struct ndr_push *, size_t) +ndr_push_union_blob: enum ndr_err_code (DATA_BLOB *, TALLOC_CTX *, void *, uint32_t, ndr_push_flags_fn_t) +ndr_push_unique_ptr: enum ndr_err_code (struct ndr_push *, const void *) +ndr_push_winreg_Data: enum ndr_err_code (struct ndr_push *, int, const union winreg_Data *) +ndr_push_winreg_Type: enum ndr_err_code (struct ndr_push *, int, enum winreg_Type) +ndr_push_zero: enum ndr_err_code (struct ndr_push *, uint32_t) +ndr_set_flags: void (uint32_t *, uint32_t) +ndr_size_DATA_BLOB: uint32_t (int, const DATA_BLOB *, int) +ndr_size_GUID: size_t (const struct GUID *, int) +ndr_size_string: uint32_t (int, const char * const *, int) +ndr_size_string_array: size_t (const char **, uint32_t, int) +ndr_size_struct: size_t (const void *, int, ndr_push_flags_fn_t) +ndr_size_union: size_t (const void *, int, uint32_t, ndr_push_flags_fn_t) +ndr_string_array_size: size_t (struct ndr_push *, const char *) +ndr_string_length: uint32_t (const void *, uint32_t) +ndr_syntax_id_equal: bool (const struct ndr_syntax_id *, const struct ndr_syntax_id *) +ndr_syntax_id_from_string: bool (const char *, struct ndr_syntax_id *) +ndr_syntax_id_null: uuid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\000", node = "\000\000\000\000\000"}, if_version = 0 +ndr_syntax_id_to_string: char *(TALLOC_CTX *, const struct ndr_syntax_id *) +ndr_token_peek: uint32_t (struct ndr_token_list **, const void *) +ndr_token_retrieve: enum ndr_err_code (struct ndr_token_list **, const void *, uint32_t *) +ndr_token_retrieve_cmp_fn: enum ndr_err_code (struct ndr_token_list **, const void *, uint32_t *, comparison_fn_t, bool) +ndr_token_store: enum ndr_err_code (TALLOC_CTX *, struct ndr_token_list **, const void *, uint32_t) +ndr_transfer_syntax_ndr: uuid = {time_low = 2324192516, time_mid = 7403, time_hi_and_version = 4553, clock_seq = "\237\350", node = "\b\000+\020H`"}, if_version = 2 +ndr_transfer_syntax_ndr64: uuid = {time_low = 1903232307, time_mid = 48826, time_hi_and_version = 18743, clock_seq = "\203\031", node = "\265\333\357\234\314\066"}, if_version = 1 diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h index c6116ed..a268f12 100644 --- a/librpc/ndr/libndr.h +++ b/librpc/ndr/libndr.h @@ -547,6 +547,7 @@ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void * uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p); uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p); uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p); +uint32_t ndr_pull_steal_switch_value(struct ndr_pull *ndr, const void *p); enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn); enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn); enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn); diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index 453f4d3..b21c8fe 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -1106,6 +1106,20 @@ _PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void * return ndr_token_peek(&ndr->switch_list, p); } +/* retrieve a switch value and remove it from the list */ +_PUBLIC_ uint32_t ndr_pull_steal_switch_value(struct ndr_pull *ndr, const void *p) +{ + enum ndr_err_code status; + uint32_t v; + + status = ndr_token_retrieve(&ndr->switch_list, p, &v); + if (!NDR_ERR_CODE_IS_SUCCESS(status)) { + return 0; + } + + return v; +} + /* pull a struct from a blob using NDR */ diff --git a/librpc/wscript_build b/librpc/wscript_build index 135b307..0b732f6 100644 --- a/librpc/wscript_build +++ b/librpc/wscript_build @@ -708,7 +708,7 @@ bld.SAMBA_LIBRARY('ndr', public_deps='samba-errors talloc samba-util', public_headers='gen_ndr/misc.h gen_ndr/ndr_misc.h ndr/libndr.h:ndr.h', header_path= [('*gen_ndr*', 'gen_ndr')], - vnum='0.0.5', + vnum='0.0.6', abi_directory='ABI', abi_match='ndr_* GUID_*', ) -- 1.9.1 From 93196d100486a4d7cf3f2ec808ba222379a5778d Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 1 Mar 2016 14:18:52 +1300 Subject: [PATCH 3/5] ndr: Use ndr_steal to avoid long lists When pulling complex structures like nt-acls, a long list of tokens may be produced. By removing tokens along the way with ndr_token_steal, future calls to retrieve from the token list are not as expensive. Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam --- pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index c53ec4a..29cdfa9 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -2093,7 +2093,7 @@ sub ParseUnionPull($$$$) { my ($self,$e,$ndr,$varname) = @_; my $switch_type = $e->{SWITCH_TYPE}; - + my $needs_deferred_switch = is_deferred_switch_non_empty($e); $self->pidl("uint32_t level;"); if (defined($switch_type)) { if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) { @@ -2117,18 +2117,24 @@ sub ParseUnionPull($$$$) $self->pidl("NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);"); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; - $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); + if (! $needs_deferred_switch) { + $self->pidl("/* This token is not used again */"); + $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);"); + } else { + $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); + } $self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type); $self->deindent; $self->pidl("}"); - if (is_deferred_switch_non_empty($e)) { - $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); - $self->indent; - $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); - $self->ParseUnionPullDeferred($e,$ndr,$varname); - $self->deindent; - $self->pidl("}"); - } + if ($needs_deferred_switch) { + $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); + $self->indent; + $self->pidl("/* The token is not needed after this. */"); + $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);"); + $self->ParseUnionPullDeferred($e,$ndr,$varname); + $self->deindent; + $self->pidl("}"); + } $self->add_deferred(); $self->end_flags($e, $ndr); -- 1.9.1 From a55e315e240045c4a3d3f20eb124328b45fa1d19 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 26 Feb 2016 16:58:09 +1300 Subject: [PATCH 4/5] ndr: inline search for ndr_token_peek() This is often a hot path, particularly with complex structures like nt-acls. Signed-off-by: Douglas Bagnall Reviewed-by: Andrew Bartlett Reviewed-by: Garming Sam --- librpc/ndr/ndr.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index b21c8fe..89bacf7 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -954,15 +954,13 @@ _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list **list, cons */ _PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key) { - enum ndr_err_code status; - uint32_t v; - - status = ndr_token_retrieve_cmp_fn(list, key, &v, NULL, false); - if (!NDR_ERR_CODE_IS_SUCCESS(status)) { - return 0; + struct ndr_token_list *tok; + for (tok = *list; tok; tok = tok->next) { + if (tok->key == key) { + return tok->value; + } } - - return v; + return 0; } /* -- 1.9.1 From 0bd29858e5bb9e980539ac387a9a96af6c2de2b4 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 1 Mar 2016 14:13:18 +1300 Subject: [PATCH 5/5] ndrdump: add quiet flag Signed-off-by: Douglas Bagnall Signed-off-by: Garming Sam Reviewed-by: Garming Sam Reviewed-by: Andrew Bartlett --- librpc/tools/ndrdump.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/librpc/tools/ndrdump.c b/librpc/tools/ndrdump.c index 2d2c229..2dbc427 100644 --- a/librpc/tools/ndrdump.c +++ b/librpc/tools/ndrdump.c @@ -184,6 +184,12 @@ static NTSTATUS ndrdump_pull_and_print_pipes(const char *function, return NT_STATUS_OK; } +static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...) +{ + /* This is here so that you can turn ndr printing off for the purposes + of benchmarking ndr parsing. */ +} + int main(int argc, const char *argv[]) { const struct ndr_interface_table *p = NULL; @@ -206,8 +212,9 @@ static NTSTATUS ndrdump_pull_and_print_pipes(const char *function, bool validate = false; bool dumpdata = false; bool assume_ndr64 = false; + bool quiet = false; int opt; - enum {OPT_CONTEXT_FILE=1000, OPT_VALIDATE, OPT_DUMP_DATA, OPT_LOAD_DSO, OPT_NDR64}; + enum {OPT_CONTEXT_FILE=1000, OPT_VALIDATE, OPT_DUMP_DATA, OPT_LOAD_DSO, OPT_NDR64, OPT_QUIET}; struct poptOption long_options[] = { POPT_AUTOHELP {"context-file", 'c', POPT_ARG_STRING, NULL, OPT_CONTEXT_FILE, "In-filename to parse first", "CTX-FILE" }, @@ -215,6 +222,7 @@ static NTSTATUS ndrdump_pull_and_print_pipes(const char *function, {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMP_DATA, "dump the hex data", NULL }, {"load-dso", 'l', POPT_ARG_STRING, NULL, OPT_LOAD_DSO, "load from shared object file", NULL }, {"ndr64", 0, POPT_ARG_NONE, NULL, OPT_NDR64, "Assume NDR64 data", NULL }, + {"quiet", 0, POPT_ARG_NONE, NULL, OPT_QUIET, "Don't actually dump anything", NULL }, POPT_COMMON_SAMBA POPT_COMMON_VERSION { NULL } @@ -255,6 +263,9 @@ static NTSTATUS ndrdump_pull_and_print_pipes(const char *function, case OPT_NDR64: assume_ndr64 = true; break; + case OPT_QUIET: + quiet = true; + break; } } @@ -399,7 +410,11 @@ static NTSTATUS ndrdump_pull_and_print_pipes(const char *function, } ndr_print = talloc_zero(mem_ctx, struct ndr_print); - ndr_print->print = ndr_print_printf_helper; + if (quiet) { + ndr_print->print = ndr_print_dummy; + } else { + ndr_print->print = ndr_print_printf_helper; + } ndr_print->depth = 1; ndr_err = ndr_pop_dcerpc_sec_verification_trailer(ndr_pull, mem_ctx, &sec_vt); -- 1.9.1