LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_string.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 190 400 47.5 %
Date: 2024-06-13 04:01:37 Functions: 10 19 52.6 %

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

Generated by: LCOV version 1.13