LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_string.c (source / functions) Hit Total Coverage
Test: coverage report for smb2.twrp.listdir_fix f886ca1c Lines: 318 433 73.4 %
Date: 2023-11-07 19:11:32 Functions: 16 19 84.2 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    routines for marshalling/unmarshalling string types
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "librpc/ndr/libndr.h"
      24             : 
      25             : /**
      26             :   pull a general string from the wire
      27             : */
      28   102224506 : _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **s)
      29             : {
      30   102224506 :         char *as=NULL;
      31      891203 :         uint32_t len1, ofs, len2;
      32      891203 :         uint16_t len3;
      33   102224506 :         size_t conv_src_len = 0, converted_size;
      34   102224506 :         int do_convert = 1, chset = CH_UTF16;
      35   102224506 :         unsigned byte_mul = 2;
      36   102224506 :         libndr_flags flags = ndr->flags;
      37   102224506 :         unsigned c_len_term = 0;
      38             : 
      39   102224506 :         if (!(ndr_flags & NDR_SCALARS)) {
      40           0 :                 return NDR_ERR_SUCCESS;
      41             :         }
      42             : 
      43   102224506 :         if (NDR_BE(ndr)) {
      44       24614 :                 chset = CH_UTF16BE;
      45             :         }
      46             : 
      47   102224506 :         if (flags & LIBNDR_FLAG_STR_ASCII) {
      48     1382884 :                 chset = CH_DOS;
      49     1382884 :                 byte_mul = 1;
      50     1382884 :                 flags &= ~LIBNDR_FLAG_STR_ASCII;
      51             :         }
      52             : 
      53   102224506 :         if (flags & LIBNDR_FLAG_STR_UTF8) {
      54    98972452 :                 chset = CH_UTF8;
      55    98972452 :                 byte_mul = 1;
      56    98972452 :                 flags &= ~LIBNDR_FLAG_STR_UTF8;
      57             :         }
      58             : 
      59   102224506 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
      60      524292 :                 do_convert = 0;
      61      524292 :                 byte_mul = 1;
      62      524292 :                 flags &= ~LIBNDR_FLAG_STR_RAW8;
      63             :         }
      64             : 
      65   102224506 :         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
      66   102224506 :         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
      67      403164 :                 c_len_term = 1;
      68      403164 :                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
      69             :         }
      70             : 
      71   102224506 :         switch (flags & LIBNDR_STRING_FLAGS) {
      72           0 :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
      73             :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
      74           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
      75           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
      76           0 :                 if (ofs != 0) {
      77           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%"PRI_LIBNDR_FLAGS"\n",
      78             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
      79             :                 }
      80           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
      81           0 :                 if (len2 > len1) {
      82           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING,
      83             :                                               "Bad string lengths len1=%"PRIu32" ofs=%"PRIu32" len2=%"PRIu32"\n",
      84             :                                               len1, ofs, len2);
      85           0 :                 } else if (len1 != len2) {
      86           0 :                         DEBUG(6,("len1[%"PRIu32"] != len2[%"PRIu32"] '%s'\n", len1, len2, as));
      87             :                 }
      88           0 :                 conv_src_len = len2 + c_len_term;
      89           0 :                 break;
      90             : 
      91          28 :         case LIBNDR_FLAG_STR_SIZE4:
      92             :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
      93          28 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
      94          28 :                 conv_src_len = len1 + c_len_term;
      95          28 :                 break;
      96             : 
      97        1666 :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
      98        1666 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
      99        1666 :                 conv_src_len = len1;
     100        1666 :                 byte_mul = 1; /* the length is now absolute */
     101        1666 :                 break;
     102             : 
     103           0 :         case LIBNDR_FLAG_STR_LEN4:
     104             :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
     105           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
     106           0 :                 if (ofs != 0) {
     107           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     108             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     109             :                 }
     110           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
     111           0 :                 conv_src_len = len1 + c_len_term;
     112           0 :                 break;
     113             : 
     114           0 :         case LIBNDR_FLAG_STR_SIZE2:
     115             :         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
     116           0 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
     117           0 :                 conv_src_len = len3 + c_len_term;
     118           0 :                 break;
     119             : 
     120           0 :         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
     121           0 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
     122           0 :                 conv_src_len = len3;
     123           0 :                 byte_mul = 1; /* the length is now absolute */
     124           0 :                 break;
     125             : 
     126   101117536 :         case LIBNDR_FLAG_STR_NULLTERM:
     127             :                 /*
     128             :                  * We ensure that conv_str_len cannot return 0 by
     129             :                  * requiring that there be enough bytes for at least
     130             :                  * the NULL terminator
     131             :                  */
     132   101117536 :                 if (byte_mul == 1) {
     133   100879594 :                         NDR_PULL_NEED_BYTES(ndr, 1);
     134   100879593 :                         conv_src_len = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
     135             :                 } else {
     136      237942 :                         NDR_PULL_NEED_BYTES(ndr, 2);
     137      237939 :                         conv_src_len = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
     138             :                 }
     139   100248074 :                 byte_mul = 1; /* the length is now absolute */
     140   100248074 :                 break;
     141             : 
     142     1105276 :         case LIBNDR_FLAG_STR_NOTERM:
     143     1105276 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     144           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     145             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     146             :                 }
     147     1105276 :                 conv_src_len = ndr->data_size - ndr->offset;
     148     1105276 :                 byte_mul = 1; /* the length is now absolute */
     149     1105276 :                 break;
     150             : 
     151           0 :         default:
     152           0 :                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     153             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     154             :         }
     155             : 
     156   102224502 :         NDR_PULL_NEED_BYTES(ndr, conv_src_len * byte_mul);
     157   102224502 :         if (conv_src_len == 0) {
     158           7 :                 as = talloc_strdup(ndr->current_mem_ctx, "");
     159           7 :                 converted_size = 0;
     160             :         } else {
     161   102224495 :                 if (!do_convert) {
     162     1048584 :                         as = talloc_strndup(ndr->current_mem_ctx,
     163      524292 :                                             (char *)ndr->data + ndr->offset,
     164             :                                             conv_src_len);
     165      524292 :                         if (!as) {
     166           0 :                                 return ndr_pull_error(ndr, NDR_ERR_ALLOC,
     167             :                                                       "Failed to talloc_strndup() in RAW8 ndr_string_pull()");
     168             :                         }
     169      524292 :                         converted_size = MIN(strlen(as)+1, conv_src_len);
     170   101700203 :                 } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
     171   101700203 :                                            CH_UNIX, ndr->data + ndr->offset,
     172             :                                            conv_src_len * byte_mul,
     173             :                                            &as,
     174             :                                            &converted_size)) {
     175           4 :                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     176             :                                               "Bad character conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
     177             :                 }
     178             :         }
     179             : 
     180             :         /* this is a way of detecting if a string is sent with the wrong
     181             :            termination */
     182   102224498 :         if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
     183     1106970 :                 if (as && converted_size > 0 && as[converted_size-1] == '\0') {
     184           0 :                         DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as));
     185             :                 }
     186             :         } else {
     187   101117528 :                 if (as && converted_size > 0 && as[converted_size-1] != '\0') {
     188          14 :                         DEBUG(6,("long string '%s', send without NULL termination (which was expected)\n", as));
     189             :                 }
     190             :         }
     191             : 
     192   102224498 :         NDR_CHECK(ndr_pull_advance(ndr, conv_src_len * byte_mul));
     193   102224498 :         *s = as;
     194             : 
     195   102224498 :         return NDR_ERR_SUCCESS;
     196             : }
     197             : 
     198             : 
     199             : /**
     200             :   push a general string onto the wire
     201             : */
     202     5171971 : _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *s)
     203             : {
     204       27659 :         ssize_t s_len, c_len;
     205       27659 :         size_t d_len;
     206     5171971 :         int do_convert = 1, chset = CH_UTF16;
     207     5171971 :         libndr_flags flags = ndr->flags;
     208     5171971 :         unsigned byte_mul = 2;
     209     5171971 :         uint8_t *dest = NULL;
     210             : 
     211     5171971 :         if (!(ndr_flags & NDR_SCALARS)) {
     212           0 :                 return NDR_ERR_SUCCESS;
     213             :         }
     214             : 
     215     5171971 :         if (NDR_BE(ndr)) {
     216       37187 :                 chset = CH_UTF16BE;
     217             :         }
     218             : 
     219     5171971 :         s_len = s?strlen(s):0;
     220             : 
     221     5171971 :         if (flags & LIBNDR_FLAG_STR_ASCII) {
     222      217574 :                 chset = CH_DOS;
     223      217574 :                 byte_mul = 1;
     224      217574 :                 flags &= ~LIBNDR_FLAG_STR_ASCII;
     225             :         }
     226             : 
     227     5171971 :         if (flags & LIBNDR_FLAG_STR_UTF8) {
     228     2814683 :                 chset = CH_UTF8;
     229     2814683 :                 byte_mul = 1;
     230     2814683 :                 flags &= ~LIBNDR_FLAG_STR_UTF8;
     231             :         }
     232             : 
     233     5171971 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
     234           4 :                 do_convert = 0;
     235           4 :                 byte_mul = 1;
     236           4 :                 flags &= ~LIBNDR_FLAG_STR_RAW8;
     237             :         }
     238             : 
     239     5171971 :         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
     240             : 
     241     5171971 :         if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
     242     3407722 :                 s_len++;
     243             :         }
     244             : 
     245     5171971 :         if (s_len == 0) {
     246         133 :                 d_len = 0;
     247         133 :                 dest = (uint8_t *)talloc_strdup(ndr, "");
     248     5171838 :         } else if (!do_convert) {
     249           4 :                 d_len = s_len;
     250           4 :                 dest = (uint8_t *)talloc_strndup(ndr, s, s_len);
     251     5171834 :         } else if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
     252             :                                           &dest, &d_len))
     253             :         {
     254           4 :                 return ndr_push_error(ndr, NDR_ERR_CHARCNV,
     255             :                                       "Bad character push conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
     256             :         }
     257             : 
     258     5171967 :         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
     259        2727 :                 c_len = d_len;
     260        2727 :                 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
     261     5169240 :         } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
     262     1484483 :                 c_len = (d_len / byte_mul)-1;
     263     1484483 :                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
     264             :         } else {
     265     3684757 :                 c_len = d_len / byte_mul;
     266             :         }
     267             : 
     268     5171967 :         switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
     269           0 :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
     270           0 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
     271           0 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
     272           0 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
     273           0 :                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
     274           0 :                 break;
     275             : 
     276           0 :         case LIBNDR_FLAG_STR_LEN4:
     277           0 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
     278           0 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
     279           0 :                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
     280           0 :                 break;
     281             : 
     282        2972 :         case LIBNDR_FLAG_STR_SIZE4:
     283        2972 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
     284        2972 :                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
     285        1065 :                 break;
     286             : 
     287           0 :         case LIBNDR_FLAG_STR_SIZE2:
     288           0 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
     289           0 :                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
     290           0 :                 break;
     291             : 
     292     3407718 :         case LIBNDR_FLAG_STR_NULLTERM:
     293     3407718 :                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
     294     3391934 :                 break;
     295             : 
     296     1761277 :         default:
     297     1761277 :                 if (ndr->flags & LIBNDR_FLAG_REMAINING) {
     298     1761277 :                         NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
     299     1751313 :                         break;
     300             :                 }
     301             : 
     302           0 :                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     303             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     304             :         }
     305             : 
     306     5171967 :         talloc_free(dest);
     307             : 
     308     5171967 :         return NDR_ERR_SUCCESS;
     309             : }
     310             : 
     311             : /**
     312             :   push a general string onto the wire
     313             : */
     314           0 : _PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
     315             : {
     316           0 :         size_t c_len;
     317           0 :         libndr_flags flags = ndr->flags;
     318           0 :         unsigned byte_mul = 2;
     319           0 :         unsigned c_len_term = 1;
     320             : 
     321           0 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
     322           0 :                 c_len = s?strlen(s):0;
     323             :         } else {
     324           0 :                 c_len = s?strlen_m(s):0;
     325             :         }
     326             : 
     327           0 :         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
     328           0 :                 byte_mul = 1;
     329             :         }
     330             : 
     331           0 :         if (flags & LIBNDR_FLAG_STR_NOTERM) {
     332           0 :                 c_len_term = 0;
     333             :         }
     334             : 
     335           0 :         c_len = c_len + c_len_term;
     336             : 
     337           0 :         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
     338           0 :                 c_len = c_len * byte_mul;
     339             :         }
     340             : 
     341           0 :         return c_len;
     342             : }
     343             : 
     344      119618 : _PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
     345             : {
     346      119618 :         if (NDR_HIDE_SECRET(ndr)) {
     347          40 :                 ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
     348          40 :                 return;
     349             :         }
     350      119578 :         if (s) {
     351      118332 :                 ndr->print(ndr, "%-25s: '%s'", name, s);
     352             :         } else {
     353        1246 :                 ndr->print(ndr, "%-25s: NULL", name);
     354             :         }
     355             : }
     356             : 
     357           0 : _PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, ndr_flags_type flags)
     358             : {
     359             :         /* FIXME: Is this correct for all strings ? */
     360           0 :         if(!(*string)) return ret;
     361           0 :         return ret+strlen(*string)+1;
     362             : }
     363             : 
     364        2744 : static uint32_t guess_string_array_size(struct ndr_pull *ndr, ndr_flags_type ndr_flags)
     365             : {
     366             :         /*
     367             :          * Here we could do something clever like count the number of zeros in
     368             :          * the ndr data, but it is probably sufficient to pick a lowish number
     369             :          * (compared to the overhead of the talloc header) and let the
     370             :          * exponential resizing deal with longer arrays.
     371             :          */
     372        2744 :         return 5;
     373             : }
     374             : 
     375          52 : static enum ndr_err_code extend_string_array(struct ndr_pull *ndr,
     376             :                                              const char ***_a,
     377             :                                              uint32_t *count)
     378             : {
     379          52 :         const char **a = *_a;
     380          52 :         uint32_t inc = *count / 4 + 3;
     381          52 :         uint32_t alloc_size = *count + inc;
     382             : 
     383          52 :         if (alloc_size < *count) {
     384             :                 /* overflow ! */
     385           0 :                 return NDR_ERR_ALLOC;
     386             :         }
     387             :         /*
     388             :          * We allocate and zero two more bytes than we report back, so that
     389             :          * the string array will always be NULL terminated.
     390             :          */
     391          52 :         a = talloc_realloc(ndr->current_mem_ctx, a,
     392             :                            const char *,
     393             :                            alloc_size);
     394          52 :         NDR_ERR_HAVE_NO_MEMORY(a);
     395             : 
     396          52 :         memset(a + *count, 0, inc * sizeof(a[0]));
     397          52 :         *_a = a;
     398          52 :         *count = alloc_size - 2;
     399          52 :         return NDR_ERR_SUCCESS;
     400             : }
     401             : 
     402             : /**
     403             :   pull a general string array from the wire
     404             : */
     405        2758 : _PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char ***_a)
     406             : {
     407        2758 :         const char **a = NULL;
     408          14 :         uint32_t count;
     409        2758 :         libndr_flags flags = ndr->flags;
     410        2758 :         libndr_flags saved_flags = ndr->flags;
     411          14 :         uint32_t alloc_size;
     412             : 
     413        2758 :         if (!(ndr_flags & NDR_SCALARS)) {
     414           0 :                 return NDR_ERR_SUCCESS;
     415             :         }
     416             : 
     417        2758 :         alloc_size = guess_string_array_size(ndr, ndr_flags);
     418        2758 :         a = talloc_zero_array(ndr->current_mem_ctx, const char *, alloc_size + 2);
     419        2758 :         NDR_ERR_HAVE_NO_MEMORY(a);
     420             : 
     421        2758 :         switch (flags & (LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_NOTERM)) {
     422        2744 :         case LIBNDR_FLAG_STR_NULLTERM:
     423             :                 /*
     424             :                  * here the strings are null terminated
     425             :                  * but also the array is null terminated if LIBNDR_FLAG_REMAINING
     426             :                  * is specified
     427             :                  */
     428      527043 :                 for (count = 0;; count++) {
     429      524312 :                         TALLOC_CTX *tmp_ctx;
     430      529080 :                         const char *s = NULL;
     431      529080 :                         if (count == alloc_size) {
     432          52 :                                 NDR_CHECK(extend_string_array(ndr,
     433             :                                                               &a,
     434             :                                                               &alloc_size));
     435             :                         }
     436             : 
     437      529080 :                         tmp_ctx = ndr->current_mem_ctx;
     438      529080 :                         ndr->current_mem_ctx = a;
     439      529080 :                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
     440      529080 :                         ndr->current_mem_ctx = tmp_ctx;
     441      529080 :                         if ((ndr->data_size - ndr->offset) == 0 && ndr->flags & LIBNDR_FLAG_REMAINING)
     442             :                         {
     443          21 :                                 a[count] = s;
     444          21 :                                 break;
     445             :                         }
     446      529059 :                         if (strcmp("", s)==0) {
     447        2736 :                                 a[count] = NULL;
     448        2736 :                                 break;
     449             :                         } else {
     450      526323 :                                 a[count] = s;
     451             :                         }
     452             :                 }
     453             : 
     454        2757 :                 *_a =a;
     455        2757 :                 break;
     456             : 
     457           1 :         case LIBNDR_FLAG_STR_NOTERM:
     458           1 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     459           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     460             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     461             :                 }
     462             :                 /*
     463             :                  * here the strings are not null terminated
     464             :                  * but separated by a null terminator
     465             :                  *
     466             :                  * which means the same as:
     467             :                  * Every string is null terminated except the last
     468             :                  * string is terminated by the end of the buffer
     469             :                  *
     470             :                  * as LIBNDR_FLAG_STR_NULLTERM also end at the end
     471             :                  * of the buffer, we can pull each string with this flag
     472             :                  *
     473             :                  * The big difference with the case LIBNDR_FLAG_STR_NOTERM +
     474             :                  * LIBNDR_FLAG_REMAINING is that the last string will not be null terminated
     475             :                  */
     476           1 :                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
     477           1 :                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
     478             : 
     479           1 :                 for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
     480           1 :                         TALLOC_CTX *tmp_ctx;
     481           1 :                         const char *s = NULL;
     482           1 :                         if (count == alloc_size) {
     483           1 :                                 NDR_CHECK(extend_string_array(ndr,
     484             :                                                               &a,
     485             :                                                               &alloc_size));
     486             :                         }
     487             : 
     488           1 :                         tmp_ctx = ndr->current_mem_ctx;
     489           1 :                         ndr->current_mem_ctx = a;
     490           1 :                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
     491           0 :                         ndr->current_mem_ctx = tmp_ctx;
     492           0 :                         a[count] = s;
     493             :                 }
     494             : 
     495           0 :                 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 1);
     496           0 :                 NDR_ERR_HAVE_NO_MEMORY(a);
     497           0 :                 *_a = a;
     498           0 :                 break;
     499             : 
     500           0 :         default:
     501           0 :                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     502             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     503             :         }
     504             : 
     505        2757 :         ndr->flags = saved_flags;
     506        2757 :         return NDR_ERR_SUCCESS;
     507             : }
     508             : 
     509             : /**
     510             :   push a general string array onto the wire
     511             : */
     512       38598 : _PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char **a)
     513             : {
     514         201 :         uint32_t count;
     515       38598 :         libndr_flags flags = ndr->flags;
     516       38598 :         libndr_flags saved_flags = ndr->flags;
     517             : 
     518       38598 :         if (!(ndr_flags & NDR_SCALARS)) {
     519           0 :                 return NDR_ERR_SUCCESS;
     520             :         }
     521             : 
     522       38598 :         switch (flags & LIBNDR_STRING_FLAGS) {
     523        6609 :         case LIBNDR_FLAG_STR_NULLTERM:
     524       14272 :                 for (count = 0; a && a[count]; count++) {
     525        7661 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
     526             :                 }
     527             :                 /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
     528        6611 :                 if (!(flags & LIBNDR_FLAG_REMAINING))
     529             :                 {
     530        6591 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
     531             :                 }
     532        6609 :                 break;
     533             : 
     534       31987 :         case LIBNDR_FLAG_STR_NOTERM:
     535       31987 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     536           0 :                         return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     537             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     538             :                 }
     539             : 
     540      131190 :                 for (count = 0; a && a[count]; count++) {
     541       99203 :                         if (count > 0) {
     542       67216 :                                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
     543       67216 :                                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
     544       67216 :                                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
     545       67216 :                                 ndr->flags = saved_flags;
     546             :                         }
     547       99203 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
     548             :                 }
     549             : 
     550       31788 :                 break;
     551             : 
     552           0 :         default:
     553           0 :                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     554             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     555             :         }
     556             : 
     557       38598 :         ndr->flags = saved_flags;
     558       38598 :         return NDR_ERR_SUCCESS;
     559             : }
     560             : 
     561          12 : _PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
     562             : {
     563          12 :         uint32_t count;
     564          12 :         uint32_t i;
     565             : 
     566          26 :         for (count = 0; a && a[count]; count++) {}
     567             : 
     568          12 :         ndr->print(ndr, "%s: ARRAY(%"PRIu32")", name, count);
     569          12 :         ndr->depth++;
     570          26 :         for (i=0;i<count;i++) {
     571          14 :                 char *idx=NULL;
     572          14 :                 if (asprintf(&idx, "[%"PRIu32"]", i) != -1) {
     573          14 :                         ndr_print_string(ndr, idx, a[i]);
     574          14 :                         free(idx);
     575             :                 }
     576             :         }
     577          12 :         ndr->depth--;
     578          12 : }
     579             : 
     580           4 : _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, libndr_flags flags)
     581             : {
     582           0 :         uint32_t i;
     583           4 :         size_t size = 0;
     584           4 :         int rawbytes = 0;
     585             : 
     586           4 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
     587           0 :                 rawbytes = 1;
     588           0 :                 flags &= ~LIBNDR_FLAG_STR_RAW8;
     589             :         }
     590             : 
     591           4 :         switch (flags & LIBNDR_STRING_FLAGS) {
     592           4 :         case LIBNDR_FLAG_STR_NULLTERM:
     593           8 :                 for (i = 0; i < count; i++) {
     594           4 :                         size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
     595             :                 }
     596           4 :                 break;
     597           0 :         case LIBNDR_FLAG_STR_NOTERM:
     598           0 :                 for (i = 0; i < count; i++) {
     599           0 :                         size += rawbytes?strlen(a[i]):strlen_m(a[i]);
     600             :                 }
     601           0 :                 break;
     602           0 :         default:
     603           0 :                 return 0;
     604             :         }
     605             : 
     606           4 :         return size;
     607             : }
     608             : 
     609             : /**
     610             :  * Return number of elements in a string including the last (zeroed) element
     611             :  */
     612           0 : _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
     613             : {
     614           0 :         uint32_t i;
     615           0 :         uint8_t zero[4] = {0,0,0,0};
     616           0 :         const char *var = (const char *)_var;
     617             : 
     618           0 :         for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
     619             : 
     620           0 :         return i+1;
     621             : }
     622             : 
     623             : /**
     624             :  * @brief Get the string length including the null terminator if available.
     625             :  *
     626             :  * This checks the string length based on the elements. The returned number
     627             :  * includes the terminating null byte(s) if found.
     628             :  *
     629             :  * @param[in]  _var    The string to calculate the length for.
     630             :  *
     631             :  * @param[in]  length  The length of the buffer passed by _var.
     632             :  *
     633             :  * @param[in]  element_size The element_size of a string char in bytes.
     634             :  *
     635             :  * @return The length of the strings or 0.
     636             :  */
     637        9374 : static uint32_t ndr_string_n_length(const void *_var,
     638             :                                     size_t length,
     639             :                                     uint32_t element_size)
     640             : {
     641        9374 :         size_t i = 0;
     642        9374 :         uint8_t zero[4] = {0,0,0,0};
     643        9374 :         const char *var = (const char *)_var;
     644          26 :         int cmp;
     645             : 
     646        9374 :         if (element_size > 4) {
     647           0 :                 return 0;
     648             :         }
     649             : 
     650      162701 :         for (i = 0; i < length; i++, var += element_size) {
     651      162667 :                 cmp = memcmp(var, zero, element_size);
     652      162667 :                 if (cmp == 0) {
     653        9316 :                         break;
     654             :                 }
     655             :         }
     656             : 
     657        9374 :         if (i == length) {
     658          34 :                 return length;
     659             :         }
     660             : 
     661        9340 :         return i + 1;
     662             : }
     663             : 
     664     9510458 : _PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
     665             : {
     666      138972 :         uint32_t i;
     667      138972 :         uint32_t save_offset;
     668             : 
     669     9510458 :         if (count == 0) {
     670           0 :                 return NDR_ERR_RANGE;
     671             :         }
     672             : 
     673     9510458 :         if (element_size && count - 1 > UINT32_MAX / element_size) {
     674           0 :                 return NDR_ERR_RANGE;
     675             :         }
     676             : 
     677     9510458 :         save_offset = ndr->offset;
     678     9510458 :         NDR_CHECK(ndr_pull_advance(ndr, (count - 1) * element_size));
     679     9510458 :         NDR_PULL_NEED_BYTES(ndr, element_size);
     680             : 
     681    21301724 :         for (i = 0; i < element_size; i++) {
     682    11791270 :                  if (ndr->data[ndr->offset+i] != 0) {
     683           2 :                         ndr->offset = save_offset;
     684             : 
     685           2 :                         return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
     686             :                  }
     687             :         }
     688             : 
     689     9510454 :         ndr->offset = save_offset;
     690             : 
     691     9510454 :         return NDR_ERR_SUCCESS;
     692             : }
     693             : 
     694    17500217 : _PUBLIC_ enum ndr_err_code ndr_pull_charset(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
     695             : {
     696      308087 :         size_t converted_size;
     697             : 
     698    17500217 :         if (length == 0) {
     699     1195452 :                 *var = talloc_strdup(ndr->current_mem_ctx, "");
     700     1195452 :                 return NDR_ERR_SUCCESS;
     701             :         }
     702             : 
     703    16304765 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
     704      460596 :                 chset = CH_UTF16BE;
     705             :         }
     706             : 
     707    16304765 :         if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
     708           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
     709             :         }
     710    16304765 :         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
     711             : 
     712    16304765 :         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
     713    16304765 :                                    ndr->data+ndr->offset, length*byte_mul,
     714             :                                    var,
     715             :                                    &converted_size))
     716             :         {
     717           0 :                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     718             :                                       "Bad character conversion");
     719             :         }
     720    16304765 :         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
     721             : 
     722    16018581 :         return NDR_ERR_SUCCESS;
     723             : }
     724             : 
     725        9368 : _PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
     726             : {
     727          20 :         size_t converted_size;
     728          20 :         uint32_t str_len;
     729             : 
     730        9368 :         if (length == 0) {
     731           0 :                 *var = talloc_strdup(ndr->current_mem_ctx, "");
     732           0 :                 return NDR_ERR_SUCCESS;
     733             :         }
     734             : 
     735        9368 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
     736           0 :                 chset = CH_UTF16BE;
     737             :         }
     738             : 
     739        9368 :         if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
     740           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
     741             :         }
     742        9368 :         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
     743             : 
     744        9368 :         str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
     745        9368 :         if (str_len == 0) {
     746           0 :                 return ndr_pull_error(ndr, NDR_ERR_LENGTH,
     747             :                                       "Invalid length");
     748             :         }
     749             : 
     750        9368 :         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
     751        9368 :                                    ndr->data+ndr->offset, str_len*byte_mul,
     752             :                                    var,
     753             :                                    &converted_size))
     754             :         {
     755           0 :                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     756             :                                       "Bad character conversion");
     757             :         }
     758        9368 :         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
     759             : 
     760        9348 :         return NDR_ERR_SUCCESS;
     761             : }
     762             : 
     763    27682426 : _PUBLIC_ enum ndr_err_code ndr_push_charset(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
     764             : {
     765      251641 :         size_t required;
     766             : 
     767    27682426 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
     768       38061 :                 chset = CH_UTF16BE;
     769             :         }
     770             : 
     771    27682426 :         if ((byte_mul != 0) && (length > SIZE_MAX/byte_mul)) {
     772           0 :                 return ndr_push_error(ndr, NDR_ERR_LENGTH, "length overflow");
     773             :         }
     774    27682426 :         required = byte_mul * length;
     775             : 
     776    27682426 :         NDR_PUSH_NEED_BYTES(ndr, required);
     777             : 
     778    27682426 :         if (required) {
     779    26689505 :                 size_t size = 0;
     780             : 
     781    26689505 :                 if (var == NULL) {
     782           2 :                         return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
     783             :                 }
     784             : 
     785    26689503 :                 if (!convert_string(CH_UNIX, chset,
     786             :                              var, strlen(var),
     787    26689503 :                              ndr->data+ndr->offset, required, &size)) {
     788           0 :                         return ndr_push_error(ndr, NDR_ERR_CHARCNV,
     789             :                                       "Bad character conversion");
     790             :                 }
     791             : 
     792             :                 /* Make sure the remaining part of the string is filled with zeroes */
     793    26689503 :                 if (size < required) {
     794    24375132 :                         memset(ndr->data+ndr->offset+size, 0, required-size);
     795             :                 }
     796             :         }
     797             : 
     798    27682424 :         ndr->offset += required;
     799             : 
     800    27682424 :         return NDR_ERR_SUCCESS;
     801             : }
     802             : 
     803       32342 : _PUBLIC_ enum ndr_err_code ndr_push_charset_to_null(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
     804             : {
     805       32342 :         const char *str = var;
     806             : 
     807       32342 :         if (str == NULL) {
     808           2 :                 str = "\0"; /* i.e. two zero bytes, for UTF16 null word. */
     809           2 :                 length = 1;
     810             :         }
     811             : 
     812       32342 :         return ndr_push_charset(ndr, ndr_flags, str, length, byte_mul, chset);
     813             : }
     814             : 
     815             : /* Return number of elements in a string in the specified charset */
     816    31538855 : _PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
     817             : {
     818    31538855 :         switch (chset) {
     819             :         /* case CH_UTF16: this has the same value as CH_UTF16LE */
     820    29177601 :         case CH_UTF16LE:
     821             :         case CH_UTF16BE:
     822             :         case CH_UTF16MUNGED:
     823             :         case CH_UTF8:
     824    29177601 :                 return strlen_m_ext_term((const char *)var, CH_UNIX, chset);
     825     2361254 :         case CH_DOS:
     826             :         case CH_UNIX:
     827     2361254 :                 return strlen((const char *)var)+1;
     828           0 :         default:
     829             :                 /* Fallback, this should never happen */
     830           0 :                 return strlen((const char *)var)+1;
     831             :         }
     832             : }

Generated by: LCOV version 1.14