libndr: Return error code from ndr_token_peek()
authorAndrew Bartlett <abartlet@samba.org>
Fri, 28 May 2021 00:18:48 +0000 (12:18 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Wed, 2 Jun 2021 03:56:36 +0000 (03:56 +0000)
This makes it safer to change our code to remove tokens after use
if failing to obtain a token would result in an error.

This means changing ndr_get_array_size() and ndr_get_array_length()
to also return an error code.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14710

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
librpc/ABI/ndr-2.0.0.sigs
librpc/ndr/libndr.h
librpc/ndr/ndr.c
librpc/ndr/ndr_basic.c
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm

index b06431b3c2c841df919d7e2bb3eaa6a2d1eba065..5089be76f30ad01d604495ae28f225a537265ff5 100644 (file)
@@ -21,8 +21,8 @@ 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_get_array_length: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t *)
+ndr_get_array_size: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t *)
 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)
@@ -257,7 +257,7 @@ 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_max_list_size: size_t (void)
-ndr_token_peek: uint32_t (struct ndr_token_list *, const void *)
+ndr_token_peek: enum ndr_err_code (struct ndr_token_list *, const void *, uint32_t *)
 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)
index 25b68db34667603dedc237f3f82e173e5a9b59b0..4a13a16167cd435d6eeb01647978f98832a299a7 100644 (file)
@@ -653,12 +653,12 @@ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
 enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list, const void *key, uint32_t *v,
                                            int(*_cmp_fn)(const void*,const void*), bool erase);
 enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list, const void *key, uint32_t *v);
-uint32_t ndr_token_peek(struct ndr_token_list *list, const void *key);
+enum ndr_err_code ndr_token_peek(struct ndr_token_list *list, const void *key, uint32_t *v);
 enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p);
-uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p);
+enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size);
 enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size);
 enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p);
-uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p);
+enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length);
 enum ndr_err_code ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length);
 enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, int ndr_flags, uint32_t count);
 enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, int ndr_flags, uint32_t count);
index c384e01e31fd98a4921a7159bdf86d8f33eb2a2e..115e617da4a6a495df6e656cf988a3bbe1dfc409 100644 (file)
@@ -148,6 +148,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
 {
        uint32_t skip = 0;
        uint32_t append = 0;
+       enum ndr_err_code ndr_err;
 
        if (ndr->relative_base_offset != 0) {
                return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
@@ -179,8 +180,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
        ndr->offset -= skip;
        ndr->data_size -= skip;
 
-       append = ndr_token_peek(&ndr->array_size_list, ndr);
-       if (append != UINT32_MAX) {
+       ndr_err = ndr_token_peek(&ndr->array_size_list, ndr, &append);
+       if (ndr_err == NDR_ERR_TOKEN) {
                /*
                 * here we assume, that ndr->data is not a
                 * talloc child of ndr.
@@ -1065,18 +1066,10 @@ _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
 /*
   peek at but don't removed a token from a ndr context
 */
-_PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list *list, const void *key)
+_PUBLIC_ enum ndr_err_code ndr_token_peek(struct ndr_token_list *list,
+                                         const void *key, uint32_t *v)
 {
-       unsigned i;
-       struct ndr_token *tokens = list->tokens;
-
-       for (i = list->count - 1; i < list->count; i--) {
-               if (tokens[i].key == key) {
-                       return tokens[i].value;
-               }
-       }
-
-       return 0;
+       return ndr_token_retrieve_cmp_fn(list, key, v, NULL, false);
 }
 
 /*
@@ -1099,9 +1092,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void
 /*
   get the stored array size field
 */
-_PUBLIC_ uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
+_PUBLIC_ enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
 {
-       return ndr_token_peek(&ndr->array_size_list, p);
+       return ndr_token_peek(&ndr->array_size_list, p, size);
 }
 
 /*
@@ -1110,7 +1103,7 @@ _PUBLIC_ uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
 _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
 {
        uint32_t stored;
-       stored = ndr_token_peek(&ndr->array_size_list, p);
+       NDR_CHECK(ndr_token_peek(&ndr->array_size_list, p, &stored));
        if (stored != size) {
                return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
                                      "Bad array size - got %u expected %u\n",
@@ -1144,9 +1137,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const voi
 /*
   get the stored array length field
 */
-_PUBLIC_ uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
+_PUBLIC_ enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
 {
-       return ndr_token_peek(&ndr->array_length_list, p);
+       return ndr_token_peek(&ndr->array_length_list, p, length);
 }
 
 /*
@@ -1155,7 +1148,7 @@ _PUBLIC_ uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
 _PUBLIC_ enum ndr_err_code ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
 {
        uint32_t stored;
-       stored = ndr_token_peek(&ndr->array_length_list, p);
+       NDR_CHECK(ndr_token_peek(&ndr->array_length_list, p, &stored));
        if (stored != length) {
                return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
                                      "Bad array length - got %u expected %u\n",
index 82d2f3cfae6155a9be76057b4e4c014626d65049..e239cfb27d9266dcd8b5f611b62728cccbf635e3 100644 (file)
@@ -805,18 +805,20 @@ _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void
 */
 _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
 {
+       enum ndr_err_code ret = NDR_ERR_SUCCESS;
        uint32_t ptr = 0;
        if (p) {
                /* Check if the pointer already exists and has an id */
-               ptr = ndr_token_peek(&ndr->full_ptr_list, p);
-               if (ptr == 0) {
-                       enum ndr_err_code ret = NDR_ERR_SUCCESS;
+               ret = ndr_token_peek(&ndr->full_ptr_list, p, &ptr);
+               if (ret == NDR_ERR_TOKEN) {
                        ndr->ptr_count++;
                        ptr = ndr->ptr_count;
                        ret = ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
                        if (ret != NDR_ERR_SUCCESS) {
                                return ret;
                        }
+               } else if (ret != NDR_ERR_SUCCESS) {
+                       return ret;
                }
        }
        return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
index 119590f669691eea1056f098f17656d49c43c2b2..011fd3fa0c4efa6e588b0e64221ca25b8f7ad35d 100644 (file)
@@ -340,20 +340,21 @@ sub ParseArrayPullGetSize($$$$$$)
 
        my $size;
 
+       my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}";
+
        if ($l->{IS_CONFORMANT}) {
-               $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")";
+               $self->pidl("NDR_CHECK(ndr_get_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_size));");
        } elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays
                $size = "ndr_get_string_size($ndr, sizeof(*$var_name))";
+               $self->pidl("$array_size = $size;");
        } else {
                $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL},
                        check_null_pointer($e, $env, sub { $self->pidl(shift); },
                                           "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"),
                        check_fully_dereferenced($e, $env));
+               $self->pidl("$array_size = $size;");
        }
 
-       $self->pidl("size_$e->{NAME}_$l->{LEVEL_INDEX} = $size;");
-       my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}";
-
        if (my $range = has_property($e, "range")) {
                my ($low, $high) = parse_range($range);
                if ($low < 0) {
@@ -385,10 +386,10 @@ sub ParseArrayPullGetLength($$$$$$;$)
                return $array_size;
        }
 
-       my $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")";
-       $self->pidl("length_$e->{NAME}_$l->{LEVEL_INDEX} = $length;");
        my $array_length = "length_$e->{NAME}_$l->{LEVEL_INDEX}";
 
+       $self->pidl("NDR_CHECK(ndr_get_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_length));");
+
        if (my $range = has_property($e, "range")) {
                my ($low, $high) = parse_range($range);
                if ($low < 0) {