LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_string.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 385 543 70.9 %
Date: 2023-11-21 12:31:41 Functions: 19 22 86.4 %

          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   101798193 : _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **s)
      29             : {
      30   101798193 :         char *as=NULL;
      31      891226 :         uint32_t len1, ofs, len2;
      32      891226 :         uint16_t len3;
      33   101798193 :         size_t conv_src_len = 0, converted_size;
      34   101798193 :         int do_convert = 1, chset = CH_UTF16;
      35   101798193 :         unsigned byte_mul = 2;
      36   101798193 :         libndr_flags flags = ndr->flags;
      37   101798193 :         unsigned c_len_term = 0;
      38             : 
      39   101798193 :         if (!(ndr_flags & NDR_SCALARS)) {
      40           0 :                 return NDR_ERR_SUCCESS;
      41             :         }
      42             : 
      43   101798193 :         if (NDR_BE(ndr)) {
      44       24910 :                 chset = CH_UTF16BE;
      45             :         }
      46             : 
      47             :         /*
      48             :          * We will check this flag, but from the unmodified
      49             :          * ndr->flags, so just remove it from flags
      50             :          */
      51   101798193 :         flags &= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL;
      52             : 
      53   101798193 :         switch (flags & LIBNDR_ENCODING_FLAGS) {
      54     1341360 :         case 0:
      55     1341360 :                 break;
      56             : 
      57     1385203 :         case LIBNDR_FLAG_STR_ASCII:
      58     1385203 :                 chset = CH_DOS;
      59     1385203 :                 byte_mul = 1;
      60     1385203 :                 break;
      61             : 
      62    98525224 :         case LIBNDR_FLAG_STR_UTF8:
      63    98525224 :                 chset = CH_UTF8;
      64    98525224 :                 byte_mul = 1;
      65    98525224 :                 break;
      66             : 
      67      524292 :         case LIBNDR_FLAG_STR_RAW8:
      68      524292 :                 do_convert = 0;
      69      524292 :                 byte_mul = 1;
      70      524292 :                 break;
      71             : 
      72           0 :         default:
      73           0 :                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
      74             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
      75             :         }
      76   101798193 :         flags &= ~LIBNDR_ENCODING_FLAGS;
      77             : 
      78   101798193 :         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
      79   101798193 :         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
      80      414215 :                 c_len_term = 1;
      81      414215 :                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
      82             :         }
      83             : 
      84   101798193 :         switch (flags & LIBNDR_STRING_FLAGS) {
      85           0 :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
      86             :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
      87           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
      88           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
      89           0 :                 if (ofs != 0) {
      90           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%"PRI_LIBNDR_FLAGS"\n",
      91             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
      92             :                 }
      93           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
      94           0 :                 if (len2 > len1) {
      95           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING,
      96             :                                               "Bad string lengths len1=%"PRIu32" ofs=%"PRIu32" len2=%"PRIu32"\n",
      97             :                                               len1, ofs, len2);
      98           0 :                 } else if (len1 != len2) {
      99           0 :                         DEBUG(6,("len1[%"PRIu32"] != len2[%"PRIu32"]\n", len1, len2));
     100             :                 }
     101           0 :                 conv_src_len = len2 + c_len_term;
     102           0 :                 break;
     103             : 
     104          28 :         case LIBNDR_FLAG_STR_SIZE4:
     105             :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
     106          28 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
     107          28 :                 conv_src_len = len1 + c_len_term;
     108          28 :                 break;
     109             : 
     110        1699 :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
     111        1699 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
     112        1699 :                 conv_src_len = len1;
     113        1699 :                 byte_mul = 1; /* the length is now absolute */
     114        1699 :                 break;
     115             : 
     116           0 :         case LIBNDR_FLAG_STR_LEN4:
     117             :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
     118           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
     119           0 :                 if (ofs != 0) {
     120           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     121             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     122             :                 }
     123           0 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
     124           0 :                 conv_src_len = len1 + c_len_term;
     125           0 :                 break;
     126             : 
     127          12 :         case LIBNDR_FLAG_STR_SIZE2:
     128             :         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
     129          12 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
     130          12 :                 conv_src_len = len3 + c_len_term;
     131          12 :                 break;
     132             : 
     133           0 :         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
     134           0 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
     135           0 :                 conv_src_len = len3;
     136           0 :                 byte_mul = 1; /* the length is now absolute */
     137           0 :                 break;
     138             : 
     139   100672660 :         case LIBNDR_FLAG_STR_NULLTERM:
     140             :                 /*
     141             :                  * We ensure that conv_src_len cannot equal 0 by
     142             :                  * requiring that there be enough bytes for at least
     143             :                  * the NULL terminator
     144             :                  */
     145   100672660 :                 if (byte_mul == 1) {
     146   100434673 :                         NDR_PULL_NEED_BYTES(ndr, 1);
     147   100434672 :                         conv_src_len = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
     148             :                 } else {
     149      237987 :                         NDR_PULL_NEED_BYTES(ndr, 2);
     150      237984 :                         conv_src_len = utf16_null_terminated_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
     151             :                 }
     152    99803189 :                 byte_mul = 1; /* the length is now absolute */
     153    99803189 :                 break;
     154             : 
     155     1123794 :         case LIBNDR_FLAG_STR_NOTERM:
     156     1123794 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     157           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     158             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     159             :                 }
     160     1123794 :                 conv_src_len = ndr->data_size - ndr->offset;
     161     1123794 :                 byte_mul = 1; /* the length is now absolute */
     162     1123794 :                 break;
     163             : 
     164           0 :         default:
     165           0 :                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     166             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     167             :         }
     168             : 
     169   101798189 :         NDR_PULL_NEED_BYTES(ndr, conv_src_len * byte_mul);
     170   101798189 :         if (conv_src_len == 0) {
     171           9 :                 as = talloc_strdup(ndr->current_mem_ctx, "");
     172           9 :                 converted_size = 0;
     173           9 :                 if (!as) {
     174           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC,
     175             :                                               "Failed to talloc_strndup() in zero-length ndr_pull_string()");
     176             :                 }
     177             :         } else {
     178   101798180 :                 if (!do_convert) {
     179     1048584 :                         as = talloc_strndup(ndr->current_mem_ctx,
     180      524292 :                                             (char *)ndr->data + ndr->offset,
     181             :                                             conv_src_len);
     182      524292 :                         if (!as) {
     183           0 :                                 return ndr_pull_error(ndr, NDR_ERR_ALLOC,
     184             :                                                       "Failed to talloc_strndup() in RAW8 ndr_pull_string()");
     185             :                         }
     186      524292 :                         converted_size = MIN(strlen(as)+1, conv_src_len);
     187   101273888 :                 } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
     188   101273888 :                                                   CH_UNIX, ndr->data + ndr->offset,
     189             :                                                   conv_src_len * byte_mul,
     190             :                                                   &as,
     191             :                                                   &converted_size)) {
     192           4 :                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     193             :                                               "Bad character conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
     194             :                 }
     195             :         }
     196             : 
     197             :         /* this is a way of detecting if a string is sent with the wrong
     198             :            termination */
     199   101798185 :         if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
     200     1125528 :                 if (converted_size > 0 && as[converted_size-1] == '\0') {
     201           3 :                         DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as));
     202             :                 }
     203             :                 /*
     204             :                  * We check the original ndr->flags as it has already
     205             :                  * been removed from the local variable flags
     206             :                  */
     207     1125528 :                 if (ndr->flags & LIBNDR_FLAG_STR_NO_EMBEDDED_NUL) {
     208        1708 :                         size_t strlen_of_unix_string = strlen(as);
     209        1708 :                         if (strlen_of_unix_string != converted_size) {
     210           5 :                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     211             :                                                       "Embedded NUL at position %zu in "
     212             :                                                       "converted string "
     213             :                                                       "(and therefore source string) "
     214             :                                                       "despite "
     215             :                                                       "LIBNDR_FLAG_STR_NO_EMBEDDED_NUL\n",
     216             :                                                       strlen_of_unix_string);
     217             :                         }
     218             :                 }
     219             :         } else {
     220             :                 /*
     221             :                  * We check the original ndr->flags as it has already
     222             :                  * been removed from the local variable flags
     223             :                  */
     224   100672657 :                 if (ndr->flags & LIBNDR_FLAG_STR_NO_EMBEDDED_NUL) {
     225           7 :                         size_t strlen_of_unix_string = strlen(as);
     226           7 :                         if (converted_size > 0 && strlen_of_unix_string != converted_size - 1) {
     227           3 :                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     228             :                                                       "Embedded NUL at position %zu in "
     229             :                                                       "converted string "
     230             :                                                       "(and therefore source string) "
     231             :                                                       "despite "
     232             :                                                       "LIBNDR_FLAG_STR_NO_EMBEDDED_NUL\n",
     233             :                                                       strlen_of_unix_string);
     234             :                         }
     235             :                 }
     236   100672654 :                 if (converted_size > 0 && as[converted_size-1] != '\0') {
     237          14 :                         DEBUG(6,("long string '%s', sent without NULL termination (which was expected)\n", as));
     238             :                 }
     239             :         }
     240             : 
     241   101798177 :         NDR_CHECK(ndr_pull_advance(ndr, conv_src_len * byte_mul));
     242   101798177 :         *s = as;
     243             : 
     244   101798177 :         return NDR_ERR_SUCCESS;
     245             : }
     246             : 
     247             : 
     248             : /**
     249             :   push a general string onto the wire
     250             : */
     251     5226471 : _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *s)
     252             : {
     253       27659 :         ssize_t s_len, c_len;
     254       27659 :         size_t d_len;
     255     5226471 :         int do_convert = 1, chset = CH_UTF16;
     256     5226471 :         libndr_flags flags = ndr->flags;
     257     5226471 :         unsigned byte_mul = 2;
     258     5226471 :         const uint8_t *dest = NULL;
     259     5226471 :         uint8_t *dest_to_free = NULL;
     260       27659 :         static const uint8_t null_byte[] = {0};
     261     5226471 :         enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
     262             : 
     263     5226471 :         if (!(ndr_flags & NDR_SCALARS)) {
     264           0 :                 return NDR_ERR_SUCCESS;
     265             :         }
     266             : 
     267     5226471 :         if (NDR_BE(ndr)) {
     268       37571 :                 chset = CH_UTF16BE;
     269             :         }
     270             : 
     271     5226471 :         s_len = s?strlen(s):0;
     272             : 
     273             :         /*
     274             :          * We will check this flag, but from the unmodified
     275             :          * ndr->flags, so just remove it from flags
     276             :          */
     277     5226471 :         flags &= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL;
     278             : 
     279     5226471 :         switch (flags & LIBNDR_ENCODING_FLAGS) {
     280     2173374 :         case 0:
     281     2173374 :                 break;
     282             : 
     283      218103 :         case LIBNDR_FLAG_STR_ASCII:
     284      218103 :                 chset = CH_DOS;
     285      218103 :                 byte_mul = 1;
     286      218103 :                 break;
     287             : 
     288     2819485 :         case LIBNDR_FLAG_STR_UTF8:
     289     2819485 :                 chset = CH_UTF8;
     290     2819485 :                 byte_mul = 1;
     291     2819485 :                 break;
     292             : 
     293           4 :         case LIBNDR_FLAG_STR_RAW8:
     294           4 :                 do_convert = 0;
     295           4 :                 byte_mul = 1;
     296           4 :                 break;
     297             : 
     298           0 :         default:
     299           0 :                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     300             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     301             :         }
     302     5226471 :         flags &= ~LIBNDR_ENCODING_FLAGS;
     303             : 
     304     5226471 :         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
     305             : 
     306     5226471 :         if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
     307     3414833 :                 s_len++;
     308             :         }
     309             : 
     310     5226471 :         if (s_len == 0) {
     311         133 :                 d_len = 0;
     312         133 :                 dest = null_byte;
     313     5226338 :         } else if (!do_convert) {
     314           4 :                 d_len = s_len;
     315           4 :                 dest = (const uint8_t *)s;
     316             :         } else {
     317       27522 :                 bool ok;
     318             : 
     319     5226334 :                 ok = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
     320             :                                            &dest_to_free, &d_len);
     321     5226334 :                 if (!ok) {
     322           4 :                         return ndr_push_error(ndr, NDR_ERR_CHARCNV,
     323             :                                               "Bad character push conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
     324             :                 }
     325             : 
     326     5226330 :                 dest = dest_to_free;
     327             :         }
     328             : 
     329     5226467 :         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
     330        2737 :                 c_len = d_len;
     331        2737 :                 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
     332     5223730 :         } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
     333     1529335 :                 c_len = (d_len / byte_mul)-1;
     334     1529335 :                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
     335             :         } else {
     336     3694395 :                 c_len = d_len / byte_mul;
     337             :         }
     338             : 
     339     5226467 :         switch (flags & LIBNDR_STRING_FLAGS) {
     340           0 :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
     341             :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
     342           0 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, c_len);
     343           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     344           0 :                         goto out;
     345             :                 }
     346           0 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, 0);
     347           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     348           0 :                         goto out;
     349             :                 }
     350           0 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, c_len);
     351           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     352           0 :                         goto out;
     353             :                 }
     354           0 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     355           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     356           0 :                         goto out;
     357             :                 }
     358           0 :                 break;
     359             : 
     360           0 :         case LIBNDR_FLAG_STR_LEN4:
     361             :         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
     362           0 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, 0);
     363           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     364           0 :                         goto out;
     365             :                 }
     366           0 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, c_len);
     367           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     368           0 :                         goto out;
     369             :                 }
     370           0 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     371           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     372           0 :                         goto out;
     373             :                 }
     374           0 :                 break;
     375             : 
     376        2982 :         case LIBNDR_FLAG_STR_SIZE4:
     377             :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
     378        2982 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, c_len);
     379        2982 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     380           0 :                         goto out;
     381             :                 }
     382        2982 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     383        2982 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     384           0 :                         goto out;
     385             :                 }
     386        1075 :                 break;
     387             : 
     388           0 :         case LIBNDR_FLAG_STR_SIZE2:
     389             :         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
     390           0 :                 ndr_err = ndr_push_uint16(ndr, NDR_SCALARS, c_len);
     391           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     392           0 :                         goto out;
     393             :                 }
     394           0 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     395           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     396           0 :                         goto out;
     397             :                 }
     398           0 :                 break;
     399             : 
     400     3414829 :         case LIBNDR_FLAG_STR_NULLTERM:
     401     3414829 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     402     3414829 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     403           0 :                         goto out;
     404             :                 }
     405     3399045 :                 break;
     406             : 
     407     1808656 :         default:
     408     1808656 :                 if (ndr->flags & LIBNDR_FLAG_REMAINING) {
     409     1808656 :                         ndr_err = ndr_push_bytes(ndr, dest, d_len);
     410     1808656 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     411           0 :                                 goto out;
     412             :                         }
     413     1798692 :                         break;
     414             :                 }
     415             : 
     416           0 :                 ndr_err = ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     417             :                                          ndr->flags & LIBNDR_STRING_FLAGS);
     418           0 :                 goto out;
     419             :         }
     420             : 
     421     5226467 : out:
     422     5226467 :         talloc_free(dest_to_free);
     423     5226467 :         return ndr_err;
     424             : }
     425             : 
     426             : /**
     427             :   push a general string onto the wire
     428             : */
     429           0 : _PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
     430             : {
     431           0 :         size_t c_len;
     432           0 :         libndr_flags flags = ndr->flags;
     433           0 :         unsigned byte_mul = 2;
     434           0 :         unsigned c_len_term = 1;
     435             : 
     436           0 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
     437           0 :                 c_len = s?strlen(s):0;
     438             :         } else {
     439           0 :                 c_len = s?strlen_m(s):0;
     440             :         }
     441             : 
     442           0 :         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
     443           0 :                 byte_mul = 1;
     444             :         }
     445             : 
     446           0 :         if (flags & LIBNDR_FLAG_STR_NOTERM) {
     447           0 :                 c_len_term = 0;
     448             :         }
     449             : 
     450           0 :         c_len = c_len + c_len_term;
     451             : 
     452           0 :         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
     453           0 :                 c_len = c_len * byte_mul;
     454             :         }
     455             : 
     456           0 :         return c_len;
     457             : }
     458             : 
     459      119668 : _PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
     460             : {
     461      119668 :         if (NDR_HIDE_SECRET(ndr)) {
     462          40 :                 ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
     463          40 :                 return;
     464             :         }
     465      119628 :         if (s) {
     466      118382 :                 ndr->print(ndr, "%-25s: '%s'", name, s);
     467             :         } else {
     468        1246 :                 ndr->print(ndr, "%-25s: NULL", name);
     469             :         }
     470             : }
     471             : 
     472           0 : _PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, ndr_flags_type flags)
     473             : {
     474             :         /* FIXME: Is this correct for all strings ? */
     475           0 :         if(!(*string)) return ret;
     476           0 :         return ret+strlen(*string)+1;
     477             : }
     478             : 
     479             : /**
     480             :   pull a UTF‐16 string from the wire
     481             : */
     482           4 : _PUBLIC_ enum ndr_err_code ndr_pull_u16string(struct ndr_pull *ndr,
     483             :                                               ndr_flags_type ndr_flags,
     484             :                                               const uint16_t **s)
     485             : {
     486           4 :         uint16_t *as = NULL;
     487           4 :         const char *const src_str = (char *)ndr->data + ndr->offset;
     488           4 :         size_t src_len = 0;
     489             : 
     490           4 :         if (!(ndr_flags & NDR_SCALARS)) {
     491           0 :                 return NDR_ERR_SUCCESS;
     492             :         }
     493             : 
     494           4 :         if (ndr->flags & LIBNDR_ENCODING_FLAGS) {
     495           0 :                 return ndr_pull_error(
     496             :                         ndr,
     497             :                         NDR_ERR_STRING,
     498             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     499             :                         "passed to ndr_pull_u16string()\n",
     500             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     501             :         }
     502             : 
     503           4 :         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
     504           4 :         case LIBNDR_FLAG_STR_NULLTERM:
     505             :                 /*
     506             :                  * We ensure that src_len cannot equal 0 by
     507             :                  * requiring that there be enough bytes for at least
     508             :                  * the NULL terminator
     509             :                  */
     510           4 :                 NDR_PULL_NEED_BYTES(ndr, 2);
     511           8 :                 src_len = utf16_null_terminated_len_n(src_str,
     512           4 :                                                       ndr->data_size -
     513           0 :                                                               ndr->offset);
     514           4 :                 break;
     515             : 
     516           0 :         default:
     517           0 :                 return ndr_pull_error(
     518             :                         ndr,
     519             :                         NDR_ERR_STRING,
     520             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     521             :                         "passed to ndr_pull_u16string()\n",
     522             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     523             :         }
     524             : 
     525           4 :         NDR_PULL_NEED_BYTES(ndr, src_len);
     526           4 :         as = talloc_utf16_strlendup(ndr->current_mem_ctx,
     527             :                                     src_str,
     528             :                                     src_len);
     529           4 :         if (as == NULL) {
     530           0 :                 return ndr_pull_error(ndr,
     531             :                                       NDR_ERR_ALLOC,
     532             :                                       "Failed to talloc_utf16_strlendup() in "
     533             :                                       "ndr_pull_u16string()");
     534             :         }
     535             : 
     536           4 :         NDR_CHECK(ndr_pull_advance(ndr, src_len));
     537           4 :         *s = as;
     538             : 
     539           4 :         return NDR_ERR_SUCCESS;
     540             : }
     541             : 
     542             : /**
     543             :   push a UTF‐16 string onto the wire
     544             : */
     545           6 : _PUBLIC_ enum ndr_err_code ndr_push_u16string(struct ndr_push *ndr,
     546             :                                               ndr_flags_type ndr_flags,
     547             :                                               const uint16_t *s)
     548             : {
     549           6 :         size_t s_len;
     550             : 
     551           6 :         if (!(ndr_flags & NDR_SCALARS)) {
     552           0 :                 return NDR_ERR_SUCCESS;
     553             :         }
     554             : 
     555           6 :         if (s == NULL) {
     556           0 :                 return ndr_push_error(
     557             :                         ndr,
     558             :                         NDR_ERR_INVALID_POINTER,
     559             :                         "NULL pointer passed to ndr_push_u16string()");
     560             :         }
     561             : 
     562           6 :         s_len = utf16_null_terminated_len(s);
     563           6 :         if (s_len > UINT32_MAX) {
     564           0 :                 return ndr_push_error(
     565             :                         ndr,
     566             :                         NDR_ERR_LENGTH,
     567             :                         "length overflow in ndr_push_u16string()");
     568             :         }
     569             : 
     570           6 :         if (ndr->flags & LIBNDR_ENCODING_FLAGS) {
     571           0 :                 return ndr_push_error(
     572             :                         ndr,
     573             :                         NDR_ERR_STRING,
     574             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     575             :                         "passed to ndr_push_u16string()\n",
     576             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     577             :         }
     578             : 
     579           6 :         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
     580           6 :         case LIBNDR_FLAG_STR_NULLTERM:
     581           6 :                 NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)s, s_len));
     582           0 :                 break;
     583             : 
     584           0 :         default:
     585           0 :                 if (ndr->flags & LIBNDR_FLAG_REMAINING) {
     586           0 :                         NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)s, s_len));
     587           0 :                         break;
     588             :                 }
     589             : 
     590           0 :                 return ndr_push_error(
     591             :                         ndr,
     592             :                         NDR_ERR_STRING,
     593             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     594             :                         "passed to ndr_push_u16string()\n",
     595             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     596             :         }
     597             : 
     598           0 :         return NDR_ERR_SUCCESS;
     599             : }
     600             : 
     601           2 : _PUBLIC_ void ndr_print_u16string(struct ndr_print *ndr,
     602             :                                   const char *name,
     603             :                                   const uint16_t *s)
     604             : {
     605           2 :         return ndr_print_array_uint8(ndr,
     606             :                                      name,
     607             :                                      (const uint8_t *)s,
     608           2 :                                      utf16_len(s));
     609             : }
     610             : 
     611        2744 : static uint32_t guess_string_array_size(struct ndr_pull *ndr, ndr_flags_type ndr_flags)
     612             : {
     613             :         /*
     614             :          * Here we could do something clever like count the number of zeros in
     615             :          * the ndr data, but it is probably sufficient to pick a lowish number
     616             :          * (compared to the overhead of the talloc header) and let the
     617             :          * exponential resizing deal with longer arrays.
     618             :          */
     619        2744 :         return 5;
     620             : }
     621             : 
     622          52 : static enum ndr_err_code extend_string_array(struct ndr_pull *ndr,
     623             :                                              const char ***_a,
     624             :                                              uint32_t *count)
     625             : {
     626          52 :         const char **a = *_a;
     627          52 :         uint32_t inc = *count / 4 + 3;
     628          52 :         uint32_t alloc_size = *count + inc;
     629             : 
     630          52 :         if (alloc_size < *count) {
     631             :                 /* overflow ! */
     632           0 :                 return NDR_ERR_ALLOC;
     633             :         }
     634             :         /*
     635             :          * We allocate and zero two more bytes than we report back, so that
     636             :          * the string array will always be NULL terminated.
     637             :          */
     638          52 :         a = talloc_realloc(ndr->current_mem_ctx, a,
     639             :                            const char *,
     640             :                            alloc_size);
     641          52 :         NDR_ERR_HAVE_NO_MEMORY(a);
     642             : 
     643          52 :         memset(a + *count, 0, inc * sizeof(a[0]));
     644          52 :         *_a = a;
     645          52 :         *count = alloc_size - 2;
     646          52 :         return NDR_ERR_SUCCESS;
     647             : }
     648             : 
     649             : /**
     650             :   pull a general string array from the wire
     651             : */
     652        2758 : _PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char ***_a)
     653             : {
     654        2758 :         const char **a = NULL;
     655          14 :         uint32_t count;
     656        2758 :         libndr_flags flags = ndr->flags;
     657        2758 :         libndr_flags saved_flags = ndr->flags;
     658          14 :         uint32_t alloc_size;
     659             : 
     660        2758 :         if (!(ndr_flags & NDR_SCALARS)) {
     661           0 :                 return NDR_ERR_SUCCESS;
     662             :         }
     663             : 
     664        2758 :         alloc_size = guess_string_array_size(ndr, ndr_flags);
     665        2758 :         a = talloc_zero_array(ndr->current_mem_ctx, const char *, alloc_size + 2);
     666        2758 :         NDR_ERR_HAVE_NO_MEMORY(a);
     667             : 
     668        2758 :         switch (flags & (LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_NOTERM)) {
     669        2744 :         case LIBNDR_FLAG_STR_NULLTERM:
     670             :                 /*
     671             :                  * here the strings are null terminated
     672             :                  * but also the array is null terminated if LIBNDR_FLAG_REMAINING
     673             :                  * is specified
     674             :                  */
     675      527043 :                 for (count = 0;; count++) {
     676      524312 :                         TALLOC_CTX *tmp_ctx;
     677      529080 :                         const char *s = NULL;
     678      529080 :                         if (count == alloc_size) {
     679          52 :                                 NDR_CHECK(extend_string_array(ndr,
     680             :                                                               &a,
     681             :                                                               &alloc_size));
     682             :                         }
     683             : 
     684      529080 :                         tmp_ctx = ndr->current_mem_ctx;
     685      529080 :                         ndr->current_mem_ctx = a;
     686      529080 :                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
     687      529080 :                         ndr->current_mem_ctx = tmp_ctx;
     688      529080 :                         if ((ndr->data_size - ndr->offset) == 0 && ndr->flags & LIBNDR_FLAG_REMAINING)
     689             :                         {
     690          21 :                                 a[count] = s;
     691          21 :                                 break;
     692             :                         }
     693      529059 :                         if (strcmp("", s)==0) {
     694        2736 :                                 a[count] = NULL;
     695        2736 :                                 break;
     696             :                         } else {
     697      526323 :                                 a[count] = s;
     698             :                         }
     699             :                 }
     700             : 
     701        2757 :                 *_a =a;
     702        2757 :                 break;
     703             : 
     704           1 :         case LIBNDR_FLAG_STR_NOTERM:
     705           1 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     706           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     707             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     708             :                 }
     709             :                 /*
     710             :                  * here the strings are not null terminated
     711             :                  * but separated by a null terminator
     712             :                  *
     713             :                  * which means the same as:
     714             :                  * Every string is null terminated except the last
     715             :                  * string is terminated by the end of the buffer
     716             :                  *
     717             :                  * as LIBNDR_FLAG_STR_NULLTERM also end at the end
     718             :                  * of the buffer, we can pull each string with this flag
     719             :                  *
     720             :                  * The big difference with the case LIBNDR_FLAG_STR_NOTERM +
     721             :                  * LIBNDR_FLAG_REMAINING is that the last string will not be null terminated
     722             :                  */
     723           1 :                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
     724           1 :                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
     725             : 
     726           1 :                 for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
     727           1 :                         TALLOC_CTX *tmp_ctx;
     728           1 :                         const char *s = NULL;
     729           1 :                         if (count == alloc_size) {
     730           1 :                                 NDR_CHECK(extend_string_array(ndr,
     731             :                                                               &a,
     732             :                                                               &alloc_size));
     733             :                         }
     734             : 
     735           1 :                         tmp_ctx = ndr->current_mem_ctx;
     736           1 :                         ndr->current_mem_ctx = a;
     737           1 :                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
     738           0 :                         ndr->current_mem_ctx = tmp_ctx;
     739           0 :                         a[count] = s;
     740             :                 }
     741             : 
     742           0 :                 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 1);
     743           0 :                 NDR_ERR_HAVE_NO_MEMORY(a);
     744           0 :                 *_a = a;
     745           0 :                 break;
     746             : 
     747           0 :         default:
     748           0 :                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     749             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     750             :         }
     751             : 
     752        2757 :         ndr->flags = saved_flags;
     753        2757 :         return NDR_ERR_SUCCESS;
     754             : }
     755             : 
     756             : /**
     757             :   push a general string array onto the wire
     758             : */
     759       38838 : _PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char **a)
     760             : {
     761         201 :         uint32_t count;
     762       38838 :         libndr_flags flags = ndr->flags;
     763       38838 :         libndr_flags saved_flags = ndr->flags;
     764             : 
     765       38838 :         if (!(ndr_flags & NDR_SCALARS)) {
     766           0 :                 return NDR_ERR_SUCCESS;
     767             :         }
     768             : 
     769       38838 :         switch (flags & LIBNDR_STRING_FLAGS) {
     770        6609 :         case LIBNDR_FLAG_STR_NULLTERM:
     771       14272 :                 for (count = 0; a && a[count]; count++) {
     772        7661 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
     773             :                 }
     774             :                 /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
     775        6611 :                 if (!(flags & LIBNDR_FLAG_REMAINING))
     776             :                 {
     777        6591 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
     778             :                 }
     779        6609 :                 break;
     780             : 
     781       32227 :         case LIBNDR_FLAG_STR_NOTERM:
     782       32227 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     783           0 :                         return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     784             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     785             :                 }
     786             : 
     787      132186 :                 for (count = 0; a && a[count]; count++) {
     788       99959 :                         if (count > 0) {
     789       67732 :                                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
     790       67732 :                                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
     791       67732 :                                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
     792       67732 :                                 ndr->flags = saved_flags;
     793             :                         }
     794       99959 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
     795             :                 }
     796             : 
     797       32028 :                 break;
     798             : 
     799           0 :         default:
     800           0 :                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     801             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     802             :         }
     803             : 
     804       38838 :         ndr->flags = saved_flags;
     805       38838 :         return NDR_ERR_SUCCESS;
     806             : }
     807             : 
     808          12 : _PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
     809             : {
     810          12 :         uint32_t count;
     811          12 :         uint32_t i;
     812             : 
     813          26 :         for (count = 0; a && a[count]; count++) {}
     814             : 
     815          12 :         ndr->print(ndr, "%s: ARRAY(%"PRIu32")", name, count);
     816          12 :         ndr->depth++;
     817          26 :         for (i=0;i<count;i++) {
     818          14 :                 char *idx=NULL;
     819          14 :                 if (asprintf(&idx, "[%"PRIu32"]", i) != -1) {
     820          14 :                         ndr_print_string(ndr, idx, a[i]);
     821          14 :                         free(idx);
     822             :                 }
     823             :         }
     824          12 :         ndr->depth--;
     825          12 : }
     826             : 
     827           4 : _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, libndr_flags flags)
     828             : {
     829           0 :         uint32_t i;
     830           4 :         size_t size = 0;
     831           4 :         int rawbytes = 0;
     832             : 
     833           4 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
     834           0 :                 rawbytes = 1;
     835           0 :                 flags &= ~LIBNDR_FLAG_STR_RAW8;
     836             :         }
     837             : 
     838           4 :         switch (flags & LIBNDR_STRING_FLAGS) {
     839           4 :         case LIBNDR_FLAG_STR_NULLTERM:
     840           8 :                 for (i = 0; i < count; i++) {
     841           4 :                         size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
     842             :                 }
     843           4 :                 break;
     844           0 :         case LIBNDR_FLAG_STR_NOTERM:
     845           0 :                 for (i = 0; i < count; i++) {
     846           0 :                         size += rawbytes?strlen(a[i]):strlen_m(a[i]);
     847             :                 }
     848           0 :                 break;
     849           0 :         default:
     850           0 :                 return 0;
     851             :         }
     852             : 
     853           4 :         return size;
     854             : }
     855             : 
     856             : /**
     857             :  * Return number of elements in a string including the last (zeroed) element
     858             :  */
     859           0 : _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
     860             : {
     861           0 :         uint32_t i;
     862           0 :         uint8_t zero[4] = {0,0,0,0};
     863           0 :         const char *var = (const char *)_var;
     864             : 
     865           0 :         for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
     866             : 
     867           0 :         return i+1;
     868             : }
     869             : 
     870             : /**
     871             :  * @brief Get the string length including the null terminator if available.
     872             :  *
     873             :  * This checks the string length based on the elements. The returned number
     874             :  * includes the terminating null byte(s) if found.
     875             :  *
     876             :  * @param[in]  _var    The string to calculate the length for.
     877             :  *
     878             :  * @param[in]  length  The length of the buffer passed by _var.
     879             :  *
     880             :  * @param[in]  element_size The element_size of a string char in bytes.
     881             :  *
     882             :  * @return The length of the strings or 0.
     883             :  */
     884        9376 : static uint32_t ndr_string_n_length(const void *_var,
     885             :                                     size_t length,
     886             :                                     uint32_t element_size)
     887             : {
     888        9376 :         size_t i = 0;
     889        9376 :         uint8_t zero[4] = {0,0,0,0};
     890        9376 :         const char *var = (const char *)_var;
     891          26 :         int cmp;
     892             : 
     893        9376 :         if (element_size > 4) {
     894           0 :                 return 0;
     895             :         }
     896             : 
     897      162722 :         for (i = 0; i < length; i++, var += element_size) {
     898      162688 :                 cmp = memcmp(var, zero, element_size);
     899      162688 :                 if (cmp == 0) {
     900        9318 :                         break;
     901             :                 }
     902             :         }
     903             : 
     904        9376 :         if (i == length) {
     905          34 :                 return length;
     906             :         }
     907             : 
     908        9342 :         return i + 1;
     909             : }
     910             : 
     911     9578197 : _PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
     912             : {
     913      139099 :         uint32_t i;
     914      139099 :         uint32_t save_offset;
     915             : 
     916     9578197 :         if (count == 0) {
     917           0 :                 return NDR_ERR_RANGE;
     918             :         }
     919             : 
     920     9578197 :         if (element_size && count - 1 > UINT32_MAX / element_size) {
     921           0 :                 return NDR_ERR_RANGE;
     922             :         }
     923             : 
     924     9578197 :         save_offset = ndr->offset;
     925     9578197 :         NDR_CHECK(ndr_pull_advance(ndr, (count - 1) * element_size));
     926     9578197 :         NDR_PULL_NEED_BYTES(ndr, element_size);
     927             : 
     928    21422769 :         for (i = 0; i < element_size; i++) {
     929    11844576 :                 if (ndr->data[ndr->offset+i] != 0) {
     930           2 :                         ndr->offset = save_offset;
     931             : 
     932           2 :                         return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
     933             :                 }
     934             :         }
     935             : 
     936     9578193 :         ndr->offset = save_offset;
     937             : 
     938     9578193 :         return NDR_ERR_SUCCESS;
     939             : }
     940             : 
     941    17644836 : _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)
     942             : {
     943      308214 :         size_t converted_size;
     944             : 
     945    17644836 :         if (length == 0) {
     946     1203258 :                 *var = talloc_strdup(ndr->current_mem_ctx, "");
     947     1203258 :                 if (*var == NULL) {
     948           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC,
     949             :                                               "Failed to talloc_strdup() in ndr_pull_charset()");
     950             :                 }
     951     1181355 :                 return NDR_ERR_SUCCESS;
     952             :         }
     953             : 
     954    16441578 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
     955      510627 :                 chset = CH_UTF16BE;
     956             :         }
     957             : 
     958    16441578 :         if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
     959           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
     960             :         }
     961    16441578 :         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
     962             : 
     963    16441578 :         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
     964    16441578 :                                    ndr->data+ndr->offset, length*byte_mul,
     965             :                                    var,
     966             :                                    &converted_size))
     967             :         {
     968           0 :                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     969             :                                       "Bad character conversion");
     970             :         }
     971    16441578 :         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
     972             : 
     973    16155267 :         return NDR_ERR_SUCCESS;
     974             : }
     975             : 
     976        9370 : _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)
     977             : {
     978          20 :         size_t converted_size;
     979          20 :         uint32_t str_len;
     980             : 
     981        9370 :         if (length == 0) {
     982           0 :                 *var = talloc_strdup(ndr->current_mem_ctx, "");
     983           0 :                 if (*var == NULL) {
     984           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC,
     985             :                                               "Failed to talloc_strdup() in ndr_pull_charset_to_null()");
     986             :                 }
     987           0 :                 return NDR_ERR_SUCCESS;
     988             :         }
     989             : 
     990        9370 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
     991           0 :                 chset = CH_UTF16BE;
     992             :         }
     993             : 
     994        9370 :         if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
     995           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
     996             :         }
     997        9370 :         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
     998             : 
     999        9370 :         str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
    1000        9370 :         if (str_len == 0) {
    1001           0 :                 return ndr_pull_error(ndr, NDR_ERR_LENGTH,
    1002             :                                       "Invalid length");
    1003             :         }
    1004             : 
    1005        9370 :         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
    1006        9370 :                                    ndr->data+ndr->offset, str_len*byte_mul,
    1007             :                                    var,
    1008             :                                    &converted_size))
    1009             :         {
    1010           0 :                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
    1011             :                                       "Bad character conversion");
    1012             :         }
    1013        9370 :         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
    1014             : 
    1015        9350 :         return NDR_ERR_SUCCESS;
    1016             : }
    1017             : 
    1018    28015756 : _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)
    1019             : {
    1020      251895 :         size_t required;
    1021             : 
    1022    28015756 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
    1023       38933 :                 chset = CH_UTF16BE;
    1024             :         }
    1025             : 
    1026    28015756 :         if ((byte_mul != 0) && (length > SIZE_MAX/byte_mul)) {
    1027           0 :                 return ndr_push_error(ndr, NDR_ERR_LENGTH, "length overflow");
    1028             :         }
    1029    28015756 :         required = byte_mul * length;
    1030             : 
    1031    28015756 :         NDR_PUSH_NEED_BYTES(ndr, required);
    1032             : 
    1033    28015756 :         if (required) {
    1034    27014406 :                 size_t size = 0;
    1035             : 
    1036    27014406 :                 if (var == NULL) {
    1037           2 :                         return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
    1038             :                 }
    1039             : 
    1040    27014404 :                 if (!convert_string(CH_UNIX, chset,
    1041             :                                     var, strlen(var),
    1042    27014404 :                                     ndr->data+ndr->offset, required, &size)) {
    1043           0 :                         return ndr_push_error(ndr, NDR_ERR_CHARCNV,
    1044             :                                               "Bad character conversion");
    1045             :                 }
    1046             : 
    1047             :                 /* Make sure the remaining part of the string is filled with zeroes */
    1048    27014404 :                 if (size < required) {
    1049    24682526 :                         memset(ndr->data+ndr->offset+size, 0, required-size);
    1050             :                 }
    1051             :         }
    1052             : 
    1053    28015754 :         ndr->offset += required;
    1054             : 
    1055    28015754 :         return NDR_ERR_SUCCESS;
    1056             : }
    1057             : 
    1058       32350 : _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)
    1059             : {
    1060       32350 :         const char *str = var;
    1061             : 
    1062       32350 :         if (str == NULL) {
    1063           2 :                 str = "\0"; /* i.e. two zero bytes, for UTF16 null word. */
    1064           2 :                 length = 1;
    1065             :         }
    1066             : 
    1067       32350 :         return ndr_push_charset(ndr, ndr_flags, str, length, byte_mul, chset);
    1068             : }
    1069             : 
    1070             : /* Return number of elements in a string in the specified charset */
    1071    31631471 : _PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
    1072             : {
    1073    31631471 :         switch (chset) {
    1074             :         /* case CH_UTF16: this has the same value as CH_UTF16LE */
    1075    29216127 :         case CH_UTF16LE:
    1076             :         case CH_UTF16BE:
    1077             :         case CH_UTF16MUNGED:
    1078             :         case CH_UTF8:
    1079    29216127 :                 return strlen_m_ext_term((const char *)var, CH_UNIX, chset);
    1080     2415344 :         case CH_DOS:
    1081             :         case CH_UNIX:
    1082     2415344 :                 return strlen((const char *)var)+1;
    1083           0 :         default:
    1084             :                 /* Fallback, this should never happen */
    1085           0 :                 return strlen((const char *)var)+1;
    1086             :         }
    1087             : }

Generated by: LCOV version 1.14