LCOV - code coverage report
Current view: top level - librpc/ndr - ndr_string.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 387 547 70.7 %
Date: 2024-02-28 12:06:22 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   108762613 : _PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **s)
      29             : {
      30   108762613 :         char *as=NULL;
      31      901044 :         uint32_t len1, ofs, len2;
      32      901044 :         uint16_t len3;
      33   108762613 :         size_t conv_src_len = 0, converted_size;
      34   108762613 :         int do_convert = 1, chset = CH_UTF16;
      35   108762613 :         unsigned byte_mul = 2;
      36   108762613 :         libndr_flags flags = ndr->flags;
      37   108762613 :         unsigned c_len_term = 0;
      38             : 
      39   108762613 :         if (!(ndr_flags & NDR_SCALARS)) {
      40           0 :                 return NDR_ERR_SUCCESS;
      41             :         }
      42             : 
      43   108762613 :         if (NDR_BE(ndr)) {
      44       24405 :                 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   108762613 :         flags &= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL;
      52             : 
      53   108762613 :         switch (flags & LIBNDR_ENCODING_FLAGS) {
      54     1374612 :         case 0:
      55     1374612 :                 break;
      56             : 
      57     1437700 :         case LIBNDR_FLAG_STR_ASCII:
      58     1437700 :                 chset = CH_DOS;
      59     1437700 :                 byte_mul = 1;
      60     1437700 :                 break;
      61             : 
      62   105394853 :         case LIBNDR_FLAG_STR_UTF8:
      63   105394853 :                 chset = CH_UTF8;
      64   105394853 :                 byte_mul = 1;
      65   105394853 :                 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   108762613 :         flags &= ~LIBNDR_ENCODING_FLAGS;
      77             : 
      78   108762613 :         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
      79   108762613 :         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
      80      449917 :                 c_len_term = 1;
      81      449917 :                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
      82             :         }
      83             : 
      84   108762613 :         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        5139 :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
     111        5139 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
     112        5139 :                 conv_src_len = len1;
     113        5139 :                 byte_mul = 1; /* the length is now absolute */
     114        5139 :                 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          19 :         case LIBNDR_FLAG_STR_SIZE2:
     128             :         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
     129          19 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
     130          19 :                 conv_src_len = len3 + c_len_term;
     131          19 :                 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   107599804 :         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   107599804 :                 if (byte_mul == 1) {
     146   107356792 :                         NDR_PULL_NEED_BYTES(ndr, 1);
     147   107356791 :                         conv_src_len = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
     148             :                 } else {
     149      243012 :                         NDR_PULL_NEED_BYTES(ndr, 2);
     150      243009 :                         conv_src_len = utf16_null_terminated_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
     151             :                 }
     152   106724776 :                 byte_mul = 1; /* the length is now absolute */
     153   106724776 :                 break;
     154             : 
     155     1157623 :         case LIBNDR_FLAG_STR_NOTERM:
     156     1157623 :                 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     1157623 :                 conv_src_len = ndr->data_size - ndr->offset;
     161     1157623 :                 byte_mul = 1; /* the length is now absolute */
     162     1157623 :                 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   108762609 :         NDR_PULL_NEED_BYTES(ndr, conv_src_len * byte_mul);
     170   108762609 :         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   108762600 :                 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   108238308 :                 } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
     188   108238308 :                                                   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   108762605 :         if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
     200     1162804 :                 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     1162804 :                 if (ndr->flags & LIBNDR_FLAG_STR_NO_EMBEDDED_NUL) {
     208        5148 :                         size_t strlen_of_unix_string = strlen(as);
     209        5148 :                         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   107599801 :                 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   107599798 :                 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   108762597 :         NDR_CHECK(ndr_pull_advance(ndr, conv_src_len * byte_mul));
     242   108762597 :         *s = as;
     243             : 
     244   108762597 :         return NDR_ERR_SUCCESS;
     245             : }
     246             : 
     247             : 
     248             : /**
     249             :   push a general string onto the wire
     250             : */
     251     5596187 : _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *s)
     252             : {
     253       36682 :         ssize_t s_len, c_len;
     254       36682 :         size_t d_len;
     255     5596187 :         int do_convert = 1, chset = CH_UTF16;
     256     5596187 :         libndr_flags flags = ndr->flags;
     257     5596187 :         unsigned byte_mul = 2;
     258     5596187 :         const uint8_t *dest = NULL;
     259     5596187 :         uint8_t *dest_to_free = NULL;
     260       36682 :         static const uint8_t null_byte[] = {0};
     261     5596187 :         enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
     262             : 
     263     5596187 :         if (!(ndr_flags & NDR_SCALARS)) {
     264           0 :                 return NDR_ERR_SUCCESS;
     265             :         }
     266             : 
     267     5596187 :         if (NDR_BE(ndr)) {
     268       36963 :                 chset = CH_UTF16BE;
     269             :         }
     270             : 
     271     5596187 :         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     5596187 :         flags &= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL;
     278             : 
     279     5596187 :         switch (flags & LIBNDR_ENCODING_FLAGS) {
     280     2335070 :         case 0:
     281     2335070 :                 break;
     282             : 
     283      228438 :         case LIBNDR_FLAG_STR_ASCII:
     284      228438 :                 chset = CH_DOS;
     285      228438 :                 byte_mul = 1;
     286      228438 :                 break;
     287             : 
     288     3008147 :         case LIBNDR_FLAG_STR_UTF8:
     289     3008147 :                 chset = CH_UTF8;
     290     3008147 :                 byte_mul = 1;
     291     3008147 :                 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     5596187 :         flags &= ~LIBNDR_ENCODING_FLAGS;
     303             : 
     304     5596187 :         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
     305             : 
     306     5596187 :         if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
     307     3634608 :                 s_len++;
     308             :         }
     309             : 
     310     5596187 :         if (s_len == 0) {
     311         133 :                 d_len = 0;
     312         133 :                 dest = null_byte;
     313     5596054 :         } else if (!do_convert) {
     314           4 :                 d_len = s_len;
     315           4 :                 dest = (const uint8_t *)s;
     316             :         } else {
     317       36545 :                 bool ok;
     318             : 
     319     5596050 :                 ok = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
     320             :                                            &dest_to_free, &d_len);
     321     5596050 :                 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     5596046 :                 dest = dest_to_free;
     327             :         }
     328             : 
     329     5596183 :         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
     330        7028 :                 c_len = d_len;
     331        7028 :                 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
     332     5589155 :         } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
     333     1675383 :                 c_len = (d_len / byte_mul)-1;
     334     1675383 :                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
     335             :         } else {
     336     3913772 :                 c_len = d_len / byte_mul;
     337             :         }
     338             : 
     339     5596183 :         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        7273 :         case LIBNDR_FLAG_STR_SIZE4:
     377             :         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
     378        7273 :                 ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, c_len);
     379        7273 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     380           0 :                         goto out;
     381             :                 }
     382        7273 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     383        7273 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     384           0 :                         goto out;
     385             :                 }
     386        1099 :                 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     3634604 :         case LIBNDR_FLAG_STR_NULLTERM:
     401     3634604 :                 ndr_err = ndr_push_bytes(ndr, dest, d_len);
     402     3634604 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     403           0 :                         goto out;
     404             :                 }
     405     3614064 :                 break;
     406             : 
     407     1954306 :         default:
     408     1954306 :                 if (ndr->flags & LIBNDR_FLAG_REMAINING) {
     409     1954306 :                         ndr_err = ndr_push_bytes(ndr, dest, d_len);
     410     1954306 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     411           0 :                                 goto out;
     412             :                         }
     413     1944342 :                         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     5596183 : out:
     422     5596183 :         talloc_free(dest_to_free);
     423     5596183 :         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      120157 : _PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
     460             : {
     461      120157 :         if (NDR_HIDE_SECRET(ndr)) {
     462          40 :                 ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
     463          40 :                 return;
     464             :         }
     465      120117 :         if (s) {
     466      118871 :                 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 unsigned char **s)
     485             : {
     486           4 :         unsigned char *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_BE(ndr)) {
     495             :                 /*
     496             :                  * It isn’t clear how this type should be encoded in a
     497             :                  * big‐endian context.
     498             :                  */
     499           0 :                 return ndr_pull_error(
     500             :                         ndr,
     501             :                         NDR_ERR_STRING,
     502             :                         "u16string does not support big‐endian encoding\n");
     503             :         }
     504             : 
     505           4 :         if (ndr->flags & LIBNDR_ENCODING_FLAGS) {
     506           0 :                 return ndr_pull_error(
     507             :                         ndr,
     508             :                         NDR_ERR_STRING,
     509             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     510             :                         " passed to ndr_pull_u16string()\n",
     511             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     512             :         }
     513             : 
     514           4 :         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
     515           4 :         case LIBNDR_FLAG_STR_NULLTERM:
     516             :                 /*
     517             :                  * We ensure that src_len cannot equal 0 by
     518             :                  * requiring that there be enough bytes for at least
     519             :                  * the NULL terminator
     520             :                  */
     521           4 :                 NDR_PULL_NEED_BYTES(ndr, 2);
     522           8 :                 src_len = utf16_null_terminated_len_n(src_str,
     523           4 :                                                       ndr->data_size -
     524           0 :                                                               ndr->offset);
     525           4 :                 break;
     526             : 
     527           0 :         default:
     528           0 :                 return ndr_pull_error(
     529             :                         ndr,
     530             :                         NDR_ERR_STRING,
     531             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     532             :                         " passed to ndr_pull_u16string()\n",
     533             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     534             :         }
     535             : 
     536           4 :         NDR_PULL_NEED_BYTES(ndr, src_len);
     537           4 :         as = talloc_utf16_strlendup(ndr->current_mem_ctx,
     538             :                                     src_str,
     539             :                                     src_len);
     540           4 :         if (as == NULL) {
     541           0 :                 return ndr_pull_error(ndr,
     542             :                                       NDR_ERR_ALLOC,
     543             :                                       "Failed to talloc_utf16_strlendup() in "
     544             :                                       "ndr_pull_u16string()");
     545             :         }
     546             : 
     547           4 :         NDR_CHECK(ndr_pull_advance(ndr, src_len));
     548           4 :         *s = as;
     549             : 
     550           4 :         return NDR_ERR_SUCCESS;
     551             : }
     552             : 
     553             : /**
     554             :   push a UTF‐16 string onto the wire
     555             : */
     556           8 : _PUBLIC_ enum ndr_err_code ndr_push_u16string(struct ndr_push *ndr,
     557             :                                               ndr_flags_type ndr_flags,
     558             :                                               const unsigned char *s)
     559             : {
     560           8 :         size_t s_len;
     561             : 
     562           8 :         if (!(ndr_flags & NDR_SCALARS)) {
     563           0 :                 return NDR_ERR_SUCCESS;
     564             :         }
     565             : 
     566           8 :         if (NDR_BE(ndr)) {
     567             :                 /*
     568             :                  * It isn’t clear how this type should be encoded in a
     569             :                  * big‐endian context.
     570             :                  */
     571           0 :                 return ndr_push_error(
     572             :                         ndr,
     573             :                         NDR_ERR_STRING,
     574             :                         "u16string does not support big‐endian encoding\n");
     575             :         }
     576             : 
     577           8 :         if (s == NULL) {
     578           0 :                 return ndr_push_error(
     579             :                         ndr,
     580             :                         NDR_ERR_INVALID_POINTER,
     581             :                         "NULL pointer passed to ndr_push_u16string()");
     582             :         }
     583             : 
     584           8 :         s_len = utf16_null_terminated_len(s);
     585           8 :         if (s_len > UINT32_MAX) {
     586           0 :                 return ndr_push_error(
     587             :                         ndr,
     588             :                         NDR_ERR_LENGTH,
     589             :                         "length overflow in ndr_push_u16string()");
     590             :         }
     591             : 
     592           8 :         if (ndr->flags & LIBNDR_ENCODING_FLAGS) {
     593           0 :                 return ndr_push_error(
     594             :                         ndr,
     595             :                         NDR_ERR_STRING,
     596             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     597             :                         " passed to ndr_push_u16string()\n",
     598             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     599             :         }
     600             : 
     601           8 :         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
     602           8 :         case LIBNDR_FLAG_STR_NULLTERM:
     603           8 :                 NDR_CHECK(ndr_push_bytes(ndr, s, s_len));
     604           0 :                 break;
     605             : 
     606           0 :         default:
     607           0 :                 if (ndr->flags & LIBNDR_FLAG_REMAINING) {
     608           0 :                         NDR_CHECK(ndr_push_bytes(ndr, s, s_len));
     609           0 :                         break;
     610             :                 }
     611             : 
     612           0 :                 return ndr_push_error(
     613             :                         ndr,
     614             :                         NDR_ERR_STRING,
     615             :                         "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
     616             :                         " passed to ndr_push_u16string()\n",
     617             :                         ndr->flags & LIBNDR_STRING_FLAGS);
     618             :         }
     619             : 
     620           0 :         return NDR_ERR_SUCCESS;
     621             : }
     622             : 
     623           2 : _PUBLIC_ void ndr_print_u16string(struct ndr_print *ndr,
     624             :                                   const char *name,
     625             :                                   const unsigned char *s)
     626             : {
     627           2 :         return ndr_print_array_uint8(ndr,
     628             :                                      name,
     629             :                                      s,
     630           2 :                                      utf16_len(s));
     631             : }
     632             : 
     633        2744 : static uint32_t guess_string_array_size(struct ndr_pull *ndr, ndr_flags_type ndr_flags)
     634             : {
     635             :         /*
     636             :          * Here we could do something clever like count the number of zeros in
     637             :          * the ndr data, but it is probably sufficient to pick a lowish number
     638             :          * (compared to the overhead of the talloc header) and let the
     639             :          * exponential resizing deal with longer arrays.
     640             :          */
     641        2744 :         return 5;
     642             : }
     643             : 
     644          52 : static enum ndr_err_code extend_string_array(struct ndr_pull *ndr,
     645             :                                              const char ***_a,
     646             :                                              uint32_t *count)
     647             : {
     648          52 :         const char **a = *_a;
     649          52 :         uint32_t inc = *count / 4 + 3;
     650          52 :         uint32_t alloc_size = *count + inc;
     651             : 
     652          52 :         if (alloc_size < *count) {
     653             :                 /* overflow ! */
     654           0 :                 return NDR_ERR_ALLOC;
     655             :         }
     656             :         /*
     657             :          * We allocate and zero two more bytes than we report back, so that
     658             :          * the string array will always be NULL terminated.
     659             :          */
     660          52 :         a = talloc_realloc(ndr->current_mem_ctx, a,
     661             :                            const char *,
     662             :                            alloc_size);
     663          52 :         NDR_ERR_HAVE_NO_MEMORY(a);
     664             : 
     665          52 :         memset(a + *count, 0, inc * sizeof(a[0]));
     666          52 :         *_a = a;
     667          52 :         *count = alloc_size - 2;
     668          52 :         return NDR_ERR_SUCCESS;
     669             : }
     670             : 
     671             : /**
     672             :   pull a general string array from the wire
     673             : */
     674        2758 : _PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char ***_a)
     675             : {
     676        2758 :         const char **a = NULL;
     677          14 :         uint32_t count;
     678        2758 :         libndr_flags flags = ndr->flags;
     679        2758 :         libndr_flags saved_flags = ndr->flags;
     680          14 :         uint32_t alloc_size;
     681             : 
     682        2758 :         if (!(ndr_flags & NDR_SCALARS)) {
     683           0 :                 return NDR_ERR_SUCCESS;
     684             :         }
     685             : 
     686        2758 :         alloc_size = guess_string_array_size(ndr, ndr_flags);
     687        2758 :         a = talloc_zero_array(ndr->current_mem_ctx, const char *, alloc_size + 2);
     688        2758 :         NDR_ERR_HAVE_NO_MEMORY(a);
     689             : 
     690        2758 :         switch (flags & (LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_NOTERM)) {
     691        2744 :         case LIBNDR_FLAG_STR_NULLTERM:
     692             :                 /*
     693             :                  * here the strings are null terminated
     694             :                  * but also the array is null terminated if LIBNDR_FLAG_REMAINING
     695             :                  * is specified
     696             :                  */
     697      527043 :                 for (count = 0;; count++) {
     698      524312 :                         TALLOC_CTX *tmp_ctx;
     699      529080 :                         const char *s = NULL;
     700      529080 :                         if (count == alloc_size) {
     701          52 :                                 NDR_CHECK(extend_string_array(ndr,
     702             :                                                               &a,
     703             :                                                               &alloc_size));
     704             :                         }
     705             : 
     706      529080 :                         tmp_ctx = ndr->current_mem_ctx;
     707      529080 :                         ndr->current_mem_ctx = a;
     708      529080 :                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
     709      529080 :                         ndr->current_mem_ctx = tmp_ctx;
     710      529080 :                         if ((ndr->data_size - ndr->offset) == 0 && ndr->flags & LIBNDR_FLAG_REMAINING)
     711             :                         {
     712          21 :                                 a[count] = s;
     713          21 :                                 break;
     714             :                         }
     715      529059 :                         if (strcmp("", s)==0) {
     716        2736 :                                 a[count] = NULL;
     717        2736 :                                 break;
     718             :                         } else {
     719      526323 :                                 a[count] = s;
     720             :                         }
     721             :                 }
     722             : 
     723        2757 :                 *_a =a;
     724        2757 :                 break;
     725             : 
     726           1 :         case LIBNDR_FLAG_STR_NOTERM:
     727           1 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     728           0 :                         return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     729             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     730             :                 }
     731             :                 /*
     732             :                  * here the strings are not null terminated
     733             :                  * but separated by a null terminator
     734             :                  *
     735             :                  * which means the same as:
     736             :                  * Every string is null terminated except the last
     737             :                  * string is terminated by the end of the buffer
     738             :                  *
     739             :                  * as LIBNDR_FLAG_STR_NULLTERM also end at the end
     740             :                  * of the buffer, we can pull each string with this flag
     741             :                  *
     742             :                  * The big difference with the case LIBNDR_FLAG_STR_NOTERM +
     743             :                  * LIBNDR_FLAG_REMAINING is that the last string will not be null terminated
     744             :                  */
     745           1 :                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
     746           1 :                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
     747             : 
     748           1 :                 for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
     749           1 :                         TALLOC_CTX *tmp_ctx;
     750           1 :                         const char *s = NULL;
     751           1 :                         if (count == alloc_size) {
     752           1 :                                 NDR_CHECK(extend_string_array(ndr,
     753             :                                                               &a,
     754             :                                                               &alloc_size));
     755             :                         }
     756             : 
     757           1 :                         tmp_ctx = ndr->current_mem_ctx;
     758           1 :                         ndr->current_mem_ctx = a;
     759           1 :                         NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
     760           0 :                         ndr->current_mem_ctx = tmp_ctx;
     761           0 :                         a[count] = s;
     762             :                 }
     763             : 
     764           0 :                 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 1);
     765           0 :                 NDR_ERR_HAVE_NO_MEMORY(a);
     766           0 :                 *_a = a;
     767           0 :                 break;
     768             : 
     769           0 :         default:
     770           0 :                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     771             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     772             :         }
     773             : 
     774        2757 :         ndr->flags = saved_flags;
     775        2757 :         return NDR_ERR_SUCCESS;
     776             : }
     777             : 
     778             : /**
     779             :   push a general string array onto the wire
     780             : */
     781       38608 : _PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char **a)
     782             : {
     783         201 :         uint32_t count;
     784       38608 :         libndr_flags flags = ndr->flags;
     785       38608 :         libndr_flags saved_flags = ndr->flags;
     786             : 
     787       38608 :         if (!(ndr_flags & NDR_SCALARS)) {
     788           0 :                 return NDR_ERR_SUCCESS;
     789             :         }
     790             : 
     791       38608 :         switch (flags & LIBNDR_STRING_FLAGS) {
     792        6619 :         case LIBNDR_FLAG_STR_NULLTERM:
     793       14292 :                 for (count = 0; a && a[count]; count++) {
     794        7671 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
     795             :                 }
     796             :                 /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
     797        6621 :                 if (!(flags & LIBNDR_FLAG_REMAINING))
     798             :                 {
     799        6601 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
     800             :                 }
     801        6619 :                 break;
     802             : 
     803       31987 :         case LIBNDR_FLAG_STR_NOTERM:
     804       31987 :                 if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
     805           0 :                         return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS" (missing NDR_REMAINING)\n",
     806             :                                               ndr->flags & LIBNDR_STRING_FLAGS);
     807             :                 }
     808             : 
     809      131248 :                 for (count = 0; a && a[count]; count++) {
     810       99261 :                         if (count > 0) {
     811       67274 :                                 ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
     812       67274 :                                 ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
     813       67274 :                                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
     814       67274 :                                 ndr->flags = saved_flags;
     815             :                         }
     816       99261 :                         NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
     817             :                 }
     818             : 
     819       31788 :                 break;
     820             : 
     821           0 :         default:
     822           0 :                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
     823             :                                       ndr->flags & LIBNDR_STRING_FLAGS);
     824             :         }
     825             : 
     826       38608 :         ndr->flags = saved_flags;
     827       38608 :         return NDR_ERR_SUCCESS;
     828             : }
     829             : 
     830          12 : _PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
     831             : {
     832          12 :         uint32_t count;
     833          12 :         uint32_t i;
     834             : 
     835          26 :         for (count = 0; a && a[count]; count++) {}
     836             : 
     837          12 :         ndr->print(ndr, "%s: ARRAY(%"PRIu32")", name, count);
     838          12 :         ndr->depth++;
     839          26 :         for (i=0;i<count;i++) {
     840          14 :                 char *idx=NULL;
     841          14 :                 if (asprintf(&idx, "[%"PRIu32"]", i) != -1) {
     842          14 :                         ndr_print_string(ndr, idx, a[i]);
     843          14 :                         free(idx);
     844             :                 }
     845             :         }
     846          12 :         ndr->depth--;
     847          12 : }
     848             : 
     849           4 : _PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, libndr_flags flags)
     850             : {
     851           0 :         uint32_t i;
     852           4 :         size_t size = 0;
     853           4 :         int rawbytes = 0;
     854             : 
     855           4 :         if (flags & LIBNDR_FLAG_STR_RAW8) {
     856           0 :                 rawbytes = 1;
     857           0 :                 flags &= ~LIBNDR_FLAG_STR_RAW8;
     858             :         }
     859             : 
     860           4 :         switch (flags & LIBNDR_STRING_FLAGS) {
     861           4 :         case LIBNDR_FLAG_STR_NULLTERM:
     862           8 :                 for (i = 0; i < count; i++) {
     863           4 :                         size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
     864             :                 }
     865           4 :                 break;
     866           0 :         case LIBNDR_FLAG_STR_NOTERM:
     867           0 :                 for (i = 0; i < count; i++) {
     868           0 :                         size += rawbytes?strlen(a[i]):strlen_m(a[i]);
     869             :                 }
     870           0 :                 break;
     871           0 :         default:
     872           0 :                 return 0;
     873             :         }
     874             : 
     875           4 :         return size;
     876             : }
     877             : 
     878             : /**
     879             :  * Return number of elements in a string including the last (zeroed) element
     880             :  */
     881           0 : _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
     882             : {
     883           0 :         uint32_t i;
     884           0 :         uint8_t zero[4] = {0,0,0,0};
     885           0 :         const char *var = (const char *)_var;
     886             : 
     887           0 :         for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
     888             : 
     889           0 :         return i+1;
     890             : }
     891             : 
     892             : /**
     893             :  * @brief Get the string length including the null terminator if available.
     894             :  *
     895             :  * This checks the string length based on the elements. The returned number
     896             :  * includes the terminating null byte(s) if found.
     897             :  *
     898             :  * @param[in]  _var    The string to calculate the length for.
     899             :  *
     900             :  * @param[in]  length  The length of the buffer passed by _var.
     901             :  *
     902             :  * @param[in]  element_size The element_size of a string char in bytes.
     903             :  *
     904             :  * @return The length of the strings or 0.
     905             :  */
     906        9374 : static uint32_t ndr_string_n_length(const void *_var,
     907             :                                     size_t length,
     908             :                                     uint32_t element_size)
     909             : {
     910        9374 :         size_t i = 0;
     911        9374 :         uint8_t zero[4] = {0,0,0,0};
     912        9374 :         const char *var = (const char *)_var;
     913          26 :         int cmp;
     914             : 
     915        9374 :         if (element_size > 4) {
     916           0 :                 return 0;
     917             :         }
     918             : 
     919      162701 :         for (i = 0; i < length; i++, var += element_size) {
     920      162667 :                 cmp = memcmp(var, zero, element_size);
     921      162667 :                 if (cmp == 0) {
     922        9316 :                         break;
     923             :                 }
     924             :         }
     925             : 
     926        9374 :         if (i == length) {
     927          34 :                 return length;
     928             :         }
     929             : 
     930        9340 :         return i + 1;
     931             : }
     932             : 
     933     9856849 : _PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
     934             : {
     935      138858 :         uint32_t i;
     936      138858 :         uint32_t save_offset;
     937             : 
     938     9856849 :         if (count == 0) {
     939           0 :                 return NDR_ERR_RANGE;
     940             :         }
     941             : 
     942     9856849 :         if (element_size && count - 1 > UINT32_MAX / element_size) {
     943           0 :                 return NDR_ERR_RANGE;
     944             :         }
     945             : 
     946     9856849 :         save_offset = ndr->offset;
     947     9856849 :         NDR_CHECK(ndr_pull_advance(ndr, (count - 1) * element_size));
     948     9856849 :         NDR_PULL_NEED_BYTES(ndr, element_size);
     949             : 
     950    21876457 :         for (i = 0; i < element_size; i++) {
     951    12019612 :                 if (ndr->data[ndr->offset+i] != 0) {
     952           2 :                         ndr->offset = save_offset;
     953             : 
     954           2 :                         return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
     955             :                 }
     956             :         }
     957             : 
     958     9856845 :         ndr->offset = save_offset;
     959             : 
     960     9856845 :         return NDR_ERR_SUCCESS;
     961             : }
     962             : 
     963    17964669 : _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)
     964             : {
     965      307973 :         size_t converted_size;
     966             : 
     967    17964669 :         if (length == 0) {
     968     1214807 :                 *var = talloc_strdup(ndr->current_mem_ctx, "");
     969     1214807 :                 if (*var == NULL) {
     970           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC,
     971             :                                               "Failed to talloc_strdup() in ndr_pull_charset()");
     972             :                 }
     973     1192904 :                 return NDR_ERR_SUCCESS;
     974             :         }
     975             : 
     976    16749862 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
     977      469145 :                 chset = CH_UTF16BE;
     978             :         }
     979             : 
     980    16749862 :         if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
     981           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
     982             :         }
     983    16749862 :         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
     984             : 
     985    16749862 :         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
     986    16749862 :                                    ndr->data+ndr->offset, length*byte_mul,
     987             :                                    var,
     988             :                                    &converted_size))
     989             :         {
     990           0 :                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
     991             :                                       "Bad character conversion");
     992             :         }
     993    16749862 :         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
     994             : 
     995    16463792 :         return NDR_ERR_SUCCESS;
     996             : }
     997             : 
     998        9368 : _PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
     999             : {
    1000          20 :         size_t converted_size;
    1001          20 :         uint32_t str_len;
    1002             : 
    1003        9368 :         if (length == 0) {
    1004           0 :                 *var = talloc_strdup(ndr->current_mem_ctx, "");
    1005           0 :                 if (*var == NULL) {
    1006           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC,
    1007             :                                               "Failed to talloc_strdup() in ndr_pull_charset_to_null()");
    1008             :                 }
    1009           0 :                 return NDR_ERR_SUCCESS;
    1010             :         }
    1011             : 
    1012        9368 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
    1013           0 :                 chset = CH_UTF16BE;
    1014             :         }
    1015             : 
    1016        9368 :         if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
    1017           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
    1018             :         }
    1019        9368 :         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
    1020             : 
    1021        9368 :         str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
    1022        9368 :         if (str_len == 0) {
    1023           0 :                 return ndr_pull_error(ndr, NDR_ERR_LENGTH,
    1024             :                                       "Invalid length");
    1025             :         }
    1026             : 
    1027        9368 :         if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
    1028        9368 :                                    ndr->data+ndr->offset, str_len*byte_mul,
    1029             :                                    var,
    1030             :                                    &converted_size))
    1031             :         {
    1032           0 :                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
    1033             :                                       "Bad character conversion");
    1034             :         }
    1035        9368 :         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
    1036             : 
    1037        9348 :         return NDR_ERR_SUCCESS;
    1038             : }
    1039             : 
    1040    28206291 : _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)
    1041             : {
    1042      251345 :         size_t required;
    1043             : 
    1044    28206291 :         if (NDR_BE(ndr) && chset == CH_UTF16) {
    1045       38646 :                 chset = CH_UTF16BE;
    1046             :         }
    1047             : 
    1048    28206291 :         if ((byte_mul != 0) && (length > SIZE_MAX/byte_mul)) {
    1049           0 :                 return ndr_push_error(ndr, NDR_ERR_LENGTH, "length overflow");
    1050             :         }
    1051    28206291 :         required = byte_mul * length;
    1052             : 
    1053    28206291 :         NDR_PUSH_NEED_BYTES(ndr, required);
    1054             : 
    1055    28206291 :         if (required) {
    1056    27213673 :                 size_t size = 0;
    1057             : 
    1058    27213673 :                 if (var == NULL) {
    1059           2 :                         return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
    1060             :                 }
    1061             : 
    1062    27213671 :                 if (!convert_string(CH_UNIX, chset,
    1063             :                                     var, strlen(var),
    1064    27213671 :                                     ndr->data+ndr->offset, required, &size)) {
    1065           0 :                         return ndr_push_error(ndr, NDR_ERR_CHARCNV,
    1066             :                                               "Bad character conversion");
    1067             :                 }
    1068             : 
    1069             :                 /* Make sure the remaining part of the string is filled with zeroes */
    1070    27213671 :                 if (size < required) {
    1071    24884721 :                         memset(ndr->data+ndr->offset+size, 0, required-size);
    1072             :                 }
    1073             :         }
    1074             : 
    1075    28206289 :         ndr->offset += required;
    1076             : 
    1077    28206289 :         return NDR_ERR_SUCCESS;
    1078             : }
    1079             : 
    1080       32342 : _PUBLIC_ enum ndr_err_code ndr_push_charset_to_null(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *var, uint32_t length, uint8_t byte_mul, charset_t chset)
    1081             : {
    1082       32342 :         const char *str = var;
    1083             : 
    1084       32342 :         if (str == NULL) {
    1085           2 :                 str = "\0"; /* i.e. two zero bytes, for UTF16 null word. */
    1086           2 :                 length = 1;
    1087             :         }
    1088             : 
    1089       32342 :         return ndr_push_charset(ndr, ndr_flags, str, length, byte_mul, chset);
    1090             : }
    1091             : 
    1092             : /* Return number of elements in a string in the specified charset */
    1093    33681795 : _PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
    1094             : {
    1095    33681795 :         switch (chset) {
    1096             :         /* case CH_UTF16: this has the same value as CH_UTF16LE */
    1097    31204388 :         case CH_UTF16LE:
    1098             :         case CH_UTF16BE:
    1099             :         case CH_UTF16MUNGED:
    1100             :         case CH_UTF8:
    1101    31204388 :                 return strlen_m_ext_term((const char *)var, CH_UNIX, chset);
    1102     2477407 :         case CH_DOS:
    1103             :         case CH_UNIX:
    1104     2477407 :                 return strlen((const char *)var)+1;
    1105           0 :         default:
    1106             :                 /* Fallback, this should never happen */
    1107           0 :                 return strlen((const char *)var)+1;
    1108             :         }
    1109             : }

Generated by: LCOV version 1.14