Coverage Report

Created: 2025-07-23 07:04

/src/samba/librpc/ndr/ndr_string.c
Line
Count
Source (jump to first uncovered line)
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
_PUBLIC_ enum ndr_err_code ndr_pull_string(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char **s)
29
20.3M
{
30
20.3M
  char *as=NULL;
31
20.3M
  uint32_t len1, ofs, len2;
32
20.3M
  uint16_t len3;
33
20.3M
  size_t conv_src_len = 0, converted_size;
34
20.3M
  int do_convert = 1, chset = CH_UTF16;
35
20.3M
  unsigned byte_mul = 2;
36
20.3M
  libndr_flags flags = ndr->flags;
37
20.3M
  unsigned c_len_term = 0;
38
39
20.3M
  if (!(ndr_flags & NDR_SCALARS)) {
40
0
    return NDR_ERR_SUCCESS;
41
0
  }
42
43
20.3M
  if (NDR_BE(ndr)) {
44
3.47M
    chset = CH_UTF16BE;
45
3.47M
  }
46
47
  /*
48
   * We will check this flag, but from the unmodified
49
   * ndr->flags, so just remove it from flags
50
   */
51
20.3M
  flags &= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL;
52
53
20.3M
  switch (flags & LIBNDR_ENCODING_FLAGS) {
54
9.13M
  case 0:
55
9.13M
    break;
56
57
844k
  case LIBNDR_FLAG_STR_ASCII:
58
844k
    chset = CH_DOS;
59
844k
    byte_mul = 1;
60
844k
    break;
61
62
10.3M
  case LIBNDR_FLAG_STR_UTF8:
63
10.3M
    chset = CH_UTF8;
64
10.3M
    byte_mul = 1;
65
10.3M
    break;
66
67
0
  case LIBNDR_FLAG_STR_RAW8:
68
0
    do_convert = 0;
69
0
    byte_mul = 1;
70
0
    break;
71
72
0
  default:
73
0
    return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
74
20.3M
              ndr->flags & LIBNDR_STRING_FLAGS);
75
20.3M
  }
76
20.3M
  flags &= ~LIBNDR_ENCODING_FLAGS;
77
78
20.3M
  flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
79
20.3M
  if (flags & LIBNDR_FLAG_STR_CHARLEN) {
80
1.31M
    c_len_term = 1;
81
1.31M
    flags &= ~LIBNDR_FLAG_STR_CHARLEN;
82
1.31M
  }
83
84
20.3M
  switch (flags & LIBNDR_STRING_FLAGS) {
85
0
  case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
86
0
  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
0
                ndr->flags & LIBNDR_STRING_FLAGS);
92
0
    }
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
0
                "Bad string lengths len1=%"PRIu32" ofs=%"PRIu32" len2=%"PRIu32"\n",
97
0
                len1, ofs, len2);
98
0
    } else if (len1 != len2) {
99
0
      DEBUG(6,("len1[%"PRIu32"] != len2[%"PRIu32"]\n", len1, len2));
100
0
    }
101
0
    conv_src_len = len2 + c_len_term;
102
0
    break;
103
104
0
  case LIBNDR_FLAG_STR_SIZE4:
105
742k
  case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
106
742k
    NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
107
742k
    conv_src_len = len1 + c_len_term;
108
742k
    break;
109
110
158k
  case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
111
158k
    NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
112
158k
    conv_src_len = len1;
113
158k
    byte_mul = 1; /* the length is now absolute */
114
158k
    break;
115
116
0
  case LIBNDR_FLAG_STR_LEN4:
117
0
  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
0
                ndr->flags & LIBNDR_STRING_FLAGS);
122
0
    }
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
0
  case LIBNDR_FLAG_STR_SIZE2:
128
1.00M
  case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
129
1.00M
    NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
130
1.00M
    conv_src_len = len3 + c_len_term;
131
1.00M
    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
17.1M
  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
17.1M
    if (byte_mul == 1) {
146
9.44M
      NDR_PULL_NEED_BYTES(ndr, 1);
147
9.44M
      conv_src_len = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
148
9.44M
    } else {
149
7.65M
      NDR_PULL_NEED_BYTES(ndr, 2);
150
7.65M
      conv_src_len = utf16_null_terminated_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
151
7.65M
    }
152
17.0M
    byte_mul = 1; /* the length is now absolute */
153
17.0M
    break;
154
155
1.32M
  case LIBNDR_FLAG_STR_NOTERM:
156
1.32M
    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
0
                ndr->flags & LIBNDR_STRING_FLAGS);
159
0
    }
160
1.32M
    conv_src_len = ndr->data_size - ndr->offset;
161
1.32M
    byte_mul = 1; /* the length is now absolute */
162
1.32M
    break;
163
164
0
  default:
165
0
    return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
166
20.3M
              ndr->flags & LIBNDR_STRING_FLAGS);
167
20.3M
  }
168
169
20.3M
  NDR_PULL_NEED_BYTES(ndr, conv_src_len * byte_mul);
170
20.3M
  if (conv_src_len == 0) {
171
3.10M
    as = talloc_strdup(ndr->current_mem_ctx, "");
172
3.10M
    converted_size = 0;
173
3.10M
    if (!as) {
174
0
      return ndr_pull_error(ndr, NDR_ERR_ALLOC,
175
0
                "Failed to talloc_strndup() in zero-length ndr_pull_string()");
176
0
    }
177
17.2M
  } else {
178
17.2M
    if (!do_convert) {
179
0
      as = talloc_strndup(ndr->current_mem_ctx,
180
0
                          (char *)ndr->data + ndr->offset,
181
0
              conv_src_len);
182
0
      if (!as) {
183
0
        return ndr_pull_error(ndr, NDR_ERR_ALLOC,
184
0
                  "Failed to talloc_strndup() in RAW8 ndr_pull_string()");
185
0
      }
186
0
      converted_size = MIN(strlen(as)+1, conv_src_len);
187
17.2M
    } else if (!convert_string_talloc(ndr->current_mem_ctx, chset,
188
17.2M
              CH_UNIX, ndr->data + ndr->offset,
189
17.2M
              conv_src_len * byte_mul,
190
17.2M
              &as,
191
17.2M
              &converted_size)) {
192
3.50k
      return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
193
3.50k
                "Bad character conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
194
3.50k
    }
195
17.2M
  }
196
197
  /* this is a way of detecting if a string is sent with the wrong
198
     termination */
199
20.3M
  if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
200
3.23M
    if (converted_size > 0 && as[converted_size-1] == '\0') {
201
4.76k
      DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as));
202
4.76k
    }
203
    /*
204
     * We check the original ndr->flags as it has already
205
     * been removed from the local variable flags
206
     */
207
3.23M
    if (ndr->flags & LIBNDR_FLAG_STR_NO_EMBEDDED_NUL) {
208
157k
      size_t strlen_of_unix_string = strlen(as);
209
157k
      if (strlen_of_unix_string != converted_size) {
210
164
        return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
211
164
                  "Embedded NUL at position %zu in "
212
164
                  "converted string "
213
164
                  "(and therefore source string) "
214
164
                  "despite "
215
164
                  "LIBNDR_FLAG_STR_NO_EMBEDDED_NUL\n",
216
164
                  strlen_of_unix_string);
217
164
      }
218
157k
    }
219
17.0M
  } else {
220
    /*
221
     * We check the original ndr->flags as it has already
222
     * been removed from the local variable flags
223
     */
224
17.0M
    if (ndr->flags & LIBNDR_FLAG_STR_NO_EMBEDDED_NUL) {
225
0
      size_t strlen_of_unix_string = strlen(as);
226
0
      if (converted_size > 0 && strlen_of_unix_string != converted_size - 1) {
227
0
        return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
228
0
                  "Embedded NUL at position %zu in "
229
0
                  "converted string "
230
0
                  "(and therefore source string) "
231
0
                  "despite "
232
0
                  "LIBNDR_FLAG_STR_NO_EMBEDDED_NUL\n",
233
0
                  strlen_of_unix_string);
234
0
      }
235
0
    }
236
17.0M
    if (converted_size > 0 && as[converted_size-1] != '\0') {
237
97.9k
      DEBUG(6,("long string '%s', sent without NULL termination (which was expected)\n", as));
238
97.9k
    }
239
17.0M
  }
240
241
20.3M
  NDR_CHECK(ndr_pull_advance(ndr, conv_src_len * byte_mul));
242
20.3M
  *s = as;
243
244
20.3M
  return NDR_ERR_SUCCESS;
245
20.3M
}
246
247
248
/**
249
  push a general string onto the wire
250
*/
251
_PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char *s)
252
12.5M
{
253
12.5M
  ssize_t s_len, c_len;
254
12.5M
  size_t d_len;
255
12.5M
  int do_convert = 1, chset = CH_UTF16;
256
12.5M
  libndr_flags flags = ndr->flags;
257
12.5M
  unsigned byte_mul = 2;
258
12.5M
  const uint8_t *dest = NULL;
259
12.5M
  uint8_t *dest_to_free = NULL;
260
12.5M
  static const uint8_t null_byte[] = {0};
261
12.5M
  enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
262
263
12.5M
  if (!(ndr_flags & NDR_SCALARS)) {
264
0
    return NDR_ERR_SUCCESS;
265
0
  }
266
267
12.5M
  if (NDR_BE(ndr)) {
268
1.98M
    chset = CH_UTF16BE;
269
1.98M
  }
270
271
12.5M
  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
12.5M
  flags &= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL;
278
279
12.5M
  switch (flags & LIBNDR_ENCODING_FLAGS) {
280
10.2M
  case 0:
281
10.2M
    break;
282
283
243k
  case LIBNDR_FLAG_STR_ASCII:
284
243k
    chset = CH_DOS;
285
243k
    byte_mul = 1;
286
243k
    break;
287
288
2.10M
  case LIBNDR_FLAG_STR_UTF8:
289
2.10M
    chset = CH_UTF8;
290
2.10M
    byte_mul = 1;
291
2.10M
    break;
292
293
0
  case LIBNDR_FLAG_STR_RAW8:
294
0
    do_convert = 0;
295
0
    byte_mul = 1;
296
0
    break;
297
298
0
  default:
299
0
    return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
300
12.5M
              ndr->flags & LIBNDR_STRING_FLAGS);
301
12.5M
  }
302
12.5M
  flags &= ~LIBNDR_ENCODING_FLAGS;
303
304
12.5M
  flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
305
306
12.5M
  if (!(flags & LIBNDR_FLAG_STR_NOTERM)) {
307
6.56M
    s_len++;
308
6.56M
  }
309
310
12.5M
  if (s_len == 0) {
311
5.61M
    d_len = 0;
312
5.61M
    dest = null_byte;
313
6.95M
  } else if (!do_convert) {
314
0
    d_len = s_len;
315
0
    dest = (const uint8_t *)s;
316
6.95M
  } else {
317
6.95M
    bool ok;
318
319
6.95M
    ok = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len,
320
6.95M
             &dest_to_free, &d_len);
321
6.95M
    if (!ok) {
322
0
      return ndr_push_error(ndr, NDR_ERR_CHARCNV,
323
0
                "Bad character push conversion with flags 0x%"PRI_LIBNDR_FLAGS, flags);
324
0
    }
325
326
6.95M
    dest = dest_to_free;
327
6.95M
  }
328
329
12.5M
  if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
330
356k
    c_len = d_len;
331
356k
    flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
332
12.2M
  } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
333
3.99M
    c_len = (d_len / byte_mul)-1;
334
3.99M
    flags &= ~LIBNDR_FLAG_STR_CHARLEN;
335
8.21M
  } else {
336
8.21M
    c_len = d_len / byte_mul;
337
8.21M
  }
338
339
12.5M
  switch (flags & LIBNDR_STRING_FLAGS) {
340
0
  case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
341
0
  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
0
    }
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
0
    }
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
0
    }
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
0
    }
358
0
    break;
359
360
0
  case LIBNDR_FLAG_STR_LEN4:
361
0
  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
0
    }
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
0
    }
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
0
    }
374
0
    break;
375
376
0
  case LIBNDR_FLAG_STR_SIZE4:
377
570k
  case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
378
570k
    ndr_err = ndr_push_uint32(ndr, NDR_SCALARS, c_len);
379
570k
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
380
0
      goto out;
381
0
    }
382
570k
    ndr_err = ndr_push_bytes(ndr, dest, d_len);
383
570k
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
384
0
      goto out;
385
0
    }
386
570k
    break;
387
388
570k
  case LIBNDR_FLAG_STR_SIZE2:
389
924k
  case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
390
924k
    ndr_err = ndr_push_uint16(ndr, NDR_SCALARS, c_len);
391
924k
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
392
0
      goto out;
393
0
    }
394
924k
    ndr_err = ndr_push_bytes(ndr, dest, d_len);
395
924k
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
396
0
      goto out;
397
0
    }
398
924k
    break;
399
400
6.56M
  case LIBNDR_FLAG_STR_NULLTERM:
401
6.56M
    ndr_err = ndr_push_bytes(ndr, dest, d_len);
402
6.56M
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
403
0
      goto out;
404
0
    }
405
6.56M
    break;
406
407
6.56M
  default:
408
4.51M
    if (ndr->flags & LIBNDR_FLAG_REMAINING) {
409
4.51M
      ndr_err = ndr_push_bytes(ndr, dest, d_len);
410
4.51M
      if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
411
0
        goto out;
412
0
      }
413
4.51M
      break;
414
4.51M
    }
415
416
0
    ndr_err = ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
417
0
           ndr->flags & LIBNDR_STRING_FLAGS);
418
0
    goto out;
419
12.5M
  }
420
421
12.5M
out:
422
12.5M
  TALLOC_FREE(dest_to_free);
423
12.5M
  return ndr_err;
424
12.5M
}
425
426
/**
427
  push a general string onto the wire
428
*/
429
_PUBLIC_ size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
430
0
{
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
0
  } else {
439
0
    c_len = s?strlen_m(s):0;
440
0
  }
441
442
0
  if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_RAW8|LIBNDR_FLAG_STR_UTF8)) {
443
0
    byte_mul = 1;
444
0
  }
445
446
0
  if (flags & LIBNDR_FLAG_STR_NOTERM) {
447
0
    c_len_term = 0;
448
0
  }
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
0
  }
455
456
0
  return c_len;
457
0
}
458
459
_PUBLIC_ void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
460
18.3M
{
461
18.3M
  if (NDR_HIDE_SECRET(ndr)) {
462
42
    ndr->print(ndr, "%-25s: <REDACTED SECRET VALUE>", name);
463
42
    return;
464
42
  }
465
18.3M
  if (s) {
466
17.6M
    ndr->print(ndr, "%-25s: '%s'", name, s);
467
17.6M
  } else {
468
710k
    ndr->print(ndr, "%-25s: NULL", name);
469
710k
  }
470
18.3M
}
471
472
_PUBLIC_ uint32_t ndr_size_string(int ret, const char * const* string, ndr_flags_type flags)
473
0
{
474
  /* FIXME: Is this correct for all strings ? */
475
0
  if(!(*string)) return ret;
476
0
  return ret+strlen(*string)+1;
477
0
}
478
479
/**
480
  pull a UTF‐16 string from the wire
481
*/
482
_PUBLIC_ enum ndr_err_code ndr_pull_u16string(struct ndr_pull *ndr,
483
                ndr_flags_type ndr_flags,
484
                const unsigned char **s)
485
805
{
486
805
  unsigned char *as = NULL;
487
805
  const char *const src_str = (char *)ndr->data + ndr->offset;
488
805
  size_t src_len = 0;
489
490
805
  if (!(ndr_flags & NDR_SCALARS)) {
491
0
    return NDR_ERR_SUCCESS;
492
0
  }
493
494
805
  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
0
      ndr,
501
0
      NDR_ERR_STRING,
502
0
      "u16string does not support big‐endian encoding\n");
503
0
  }
504
505
805
  if (ndr->flags & LIBNDR_ENCODING_FLAGS) {
506
0
    return ndr_pull_error(
507
0
      ndr,
508
0
      NDR_ERR_STRING,
509
0
      "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
510
0
      " passed to ndr_pull_u16string()\n",
511
0
      ndr->flags & LIBNDR_STRING_FLAGS);
512
0
  }
513
514
805
  switch (ndr->flags & LIBNDR_STRING_FLAGS) {
515
805
  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
805
    NDR_PULL_NEED_BYTES(ndr, 2);
522
793
    src_len = utf16_null_terminated_len_n(src_str,
523
793
                  ndr->data_size -
524
793
                    ndr->offset);
525
793
    break;
526
527
0
  default:
528
0
    return ndr_pull_error(
529
805
      ndr,
530
805
      NDR_ERR_STRING,
531
805
      "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
532
805
      " passed to ndr_pull_u16string()\n",
533
805
      ndr->flags & LIBNDR_STRING_FLAGS);
534
805
  }
535
536
793
  NDR_PULL_NEED_BYTES(ndr, src_len);
537
793
  as = talloc_utf16_strlendup(ndr->current_mem_ctx,
538
793
            src_str,
539
793
            src_len);
540
793
  if (as == NULL) {
541
0
    return ndr_pull_error(ndr,
542
0
              NDR_ERR_ALLOC,
543
0
              "Failed to talloc_utf16_strlendup() in "
544
0
              "ndr_pull_u16string()");
545
0
  }
546
547
793
  NDR_CHECK(ndr_pull_advance(ndr, src_len));
548
793
  *s = as;
549
550
793
  return NDR_ERR_SUCCESS;
551
793
}
552
553
/**
554
  push a UTF‐16 string onto the wire
555
*/
556
_PUBLIC_ enum ndr_err_code ndr_push_u16string(struct ndr_push *ndr,
557
                ndr_flags_type ndr_flags,
558
                const unsigned char *s)
559
1.39k
{
560
1.39k
  size_t s_len;
561
562
1.39k
  if (!(ndr_flags & NDR_SCALARS)) {
563
0
    return NDR_ERR_SUCCESS;
564
0
  }
565
566
1.39k
  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
0
      ndr,
573
0
      NDR_ERR_STRING,
574
0
      "u16string does not support big‐endian encoding\n");
575
0
  }
576
577
1.39k
  if (s == NULL) {
578
0
    return ndr_push_error(
579
0
      ndr,
580
0
      NDR_ERR_INVALID_POINTER,
581
0
      "NULL pointer passed to ndr_push_u16string()");
582
0
  }
583
584
1.39k
  s_len = utf16_null_terminated_len(s);
585
1.39k
  if (s_len > UINT32_MAX) {
586
0
    return ndr_push_error(
587
0
      ndr,
588
0
      NDR_ERR_LENGTH,
589
0
      "length overflow in ndr_push_u16string()");
590
0
  }
591
592
1.39k
  if (ndr->flags & LIBNDR_ENCODING_FLAGS) {
593
0
    return ndr_push_error(
594
0
      ndr,
595
0
      NDR_ERR_STRING,
596
0
      "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
597
0
      " passed to ndr_push_u16string()\n",
598
0
      ndr->flags & LIBNDR_STRING_FLAGS);
599
0
  }
600
601
1.39k
  switch (ndr->flags & LIBNDR_STRING_FLAGS) {
602
1.39k
  case LIBNDR_FLAG_STR_NULLTERM:
603
1.39k
    NDR_CHECK(ndr_push_bytes(ndr, s, s_len));
604
1.39k
    break;
605
606
1.39k
  default:
607
0
    if (ndr->flags & LIBNDR_FLAG_REMAINING) {
608
0
      NDR_CHECK(ndr_push_bytes(ndr, s, s_len));
609
0
      break;
610
0
    }
611
612
0
    return ndr_push_error(
613
1.39k
      ndr,
614
1.39k
      NDR_ERR_STRING,
615
1.39k
      "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
616
1.39k
      " passed to ndr_push_u16string()\n",
617
1.39k
      ndr->flags & LIBNDR_STRING_FLAGS);
618
1.39k
  }
619
620
1.39k
  return NDR_ERR_SUCCESS;
621
1.39k
}
622
623
_PUBLIC_ void ndr_print_u16string(struct ndr_print *ndr,
624
          const char *name,
625
          const unsigned char *s)
626
737
{
627
737
  return ndr_print_array_uint8(ndr,
628
737
             name,
629
737
             s,
630
737
             utf16_len(s));
631
737
}
632
633
static uint32_t guess_string_array_size(struct ndr_pull *ndr, ndr_flags_type ndr_flags)
634
7.11k
{
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
7.11k
  return 5;
642
7.11k
}
643
644
static enum ndr_err_code extend_string_array(struct ndr_pull *ndr,
645
               const char ***_a,
646
               uint32_t *count)
647
29.2k
{
648
29.2k
  const char **a = *_a;
649
29.2k
  uint32_t inc = *count / 4 + 3;
650
29.2k
  uint32_t alloc_size = *count + inc;
651
652
29.2k
  if (alloc_size < *count) {
653
    /* overflow ! */
654
0
    return NDR_ERR_ALLOC;
655
0
  }
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
29.2k
  a = talloc_realloc(ndr->current_mem_ctx, a,
661
29.2k
         const char *,
662
29.2k
         alloc_size);
663
29.2k
  NDR_ERR_HAVE_NO_MEMORY(a);
664
665
29.2k
  memset(a + *count, 0, inc * sizeof(a[0]));
666
29.2k
  *_a = a;
667
29.2k
  *count = alloc_size - 2;
668
29.2k
  return NDR_ERR_SUCCESS;
669
29.2k
}
670
671
/**
672
  pull a general string array from the wire
673
*/
674
_PUBLIC_ enum ndr_err_code ndr_pull_string_array(struct ndr_pull *ndr, ndr_flags_type ndr_flags, const char ***_a)
675
7.11k
{
676
7.11k
  const char **a = NULL;
677
7.11k
  uint32_t count;
678
7.11k
  libndr_flags flags = ndr->flags;
679
7.11k
  libndr_flags saved_flags = ndr->flags;
680
7.11k
  uint32_t alloc_size;
681
682
7.11k
  if (!(ndr_flags & NDR_SCALARS)) {
683
0
    return NDR_ERR_SUCCESS;
684
0
  }
685
686
7.11k
  alloc_size = guess_string_array_size(ndr, ndr_flags);
687
7.11k
  a = talloc_zero_array(ndr->current_mem_ctx, const char *, alloc_size + 2);
688
7.11k
  NDR_ERR_HAVE_NO_MEMORY(a);
689
690
7.11k
  switch (flags & (LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_NOTERM)) {
691
6.56k
  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
3.99M
    for (count = 0;; count++) {
698
3.99M
      TALLOC_CTX *tmp_ctx;
699
3.99M
      const char *s = NULL;
700
3.99M
      if (count == alloc_size) {
701
24.8k
        NDR_CHECK(extend_string_array(ndr,
702
24.8k
                    &a,
703
24.8k
                    &alloc_size));
704
24.8k
      }
705
706
3.99M
      tmp_ctx = ndr->current_mem_ctx;
707
3.99M
      ndr->current_mem_ctx = a;
708
3.99M
      NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
709
3.99M
      ndr->current_mem_ctx = tmp_ctx;
710
3.99M
      if ((ndr->data_size - ndr->offset) == 0 && ndr->flags & LIBNDR_FLAG_REMAINING)
711
1.42k
      {
712
1.42k
        a[count] = s;
713
1.42k
        break;
714
1.42k
      }
715
3.99M
      if (strcmp("", s)==0) {
716
4.87k
        a[count] = NULL;
717
4.87k
        break;
718
3.99M
      } else {
719
3.99M
        a[count] = s;
720
3.99M
      }
721
3.99M
    }
722
723
6.30k
    *_a =a;
724
6.30k
    break;
725
726
556
  case LIBNDR_FLAG_STR_NOTERM:
727
556
    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
0
                ndr->flags & LIBNDR_STRING_FLAGS);
730
0
    }
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
556
    ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
746
556
    ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
747
748
7.19M
    for (count = 0; ((ndr->data_size - ndr->offset) > 0); count++) {
749
7.19M
      TALLOC_CTX *tmp_ctx;
750
7.19M
      const char *s = NULL;
751
7.19M
      if (count == alloc_size) {
752
4.34k
        NDR_CHECK(extend_string_array(ndr,
753
4.34k
                    &a,
754
4.34k
                    &alloc_size));
755
4.34k
      }
756
757
7.19M
      tmp_ctx = ndr->current_mem_ctx;
758
7.19M
      ndr->current_mem_ctx = a;
759
7.19M
      NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
760
7.19M
      ndr->current_mem_ctx = tmp_ctx;
761
7.19M
      a[count] = s;
762
7.19M
    }
763
764
467
    a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 1);
765
467
    NDR_ERR_HAVE_NO_MEMORY(a);
766
467
    *_a = a;
767
467
    break;
768
769
0
  default:
770
0
    return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
771
7.11k
              ndr->flags & LIBNDR_STRING_FLAGS);
772
7.11k
  }
773
774
6.76k
  ndr->flags = saved_flags;
775
6.76k
  return NDR_ERR_SUCCESS;
776
7.11k
}
777
778
/**
779
  push a general string array onto the wire
780
*/
781
_PUBLIC_ enum ndr_err_code ndr_push_string_array(struct ndr_push *ndr, ndr_flags_type ndr_flags, const char **a)
782
5.70k
{
783
5.70k
  uint32_t count;
784
5.70k
  libndr_flags flags = ndr->flags;
785
5.70k
  libndr_flags saved_flags = ndr->flags;
786
787
5.70k
  if (!(ndr_flags & NDR_SCALARS)) {
788
0
    return NDR_ERR_SUCCESS;
789
0
  }
790
791
5.70k
  switch (flags & LIBNDR_STRING_FLAGS) {
792
5.23k
  case LIBNDR_FLAG_STR_NULLTERM:
793
2.30M
    for (count = 0; a && a[count]; count++) {
794
2.30M
      NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
795
2.30M
    }
796
    /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
797
5.23k
    if (!(flags & LIBNDR_FLAG_REMAINING))
798
1.87k
    {
799
1.87k
      NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
800
1.87k
    }
801
5.23k
    break;
802
803
5.23k
  case LIBNDR_FLAG_STR_NOTERM:
804
240
    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
0
                ndr->flags & LIBNDR_STRING_FLAGS);
807
0
    }
808
809
482k
    for (count = 0; a && a[count]; count++) {
810
481k
      if (count > 0) {
811
481k
        ndr->flags &= ~(LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_REMAINING);
812
481k
        ndr->flags |= LIBNDR_FLAG_STR_NULLTERM;
813
481k
        NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
814
481k
        ndr->flags = saved_flags;
815
481k
      }
816
481k
      NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
817
481k
    }
818
819
240
    break;
820
821
240
  default:
822
227
    return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%"PRI_LIBNDR_FLAGS"\n",
823
5.70k
              ndr->flags & LIBNDR_STRING_FLAGS);
824
5.70k
  }
825
826
5.47k
  ndr->flags = saved_flags;
827
5.47k
  return NDR_ERR_SUCCESS;
828
5.70k
}
829
830
_PUBLIC_ void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
831
5.98k
{
832
5.98k
  uint32_t count;
833
5.98k
  uint32_t i;
834
835
10.2M
  for (count = 0; a && a[count]; count++) {}
836
837
5.98k
  ndr->print(ndr, "%s: ARRAY(%"PRIu32")", name, count);
838
5.98k
  ndr->depth++;
839
10.2M
  for (i=0;i<count;i++) {
840
10.2M
    char *idx=NULL;
841
10.2M
    if (asprintf(&idx, "[%"PRIu32"]", i) != -1) {
842
10.2M
      ndr_print_string(ndr, idx, a[i]);
843
10.2M
      free(idx);
844
10.2M
    }
845
10.2M
  }
846
5.98k
  ndr->depth--;
847
5.98k
}
848
849
_PUBLIC_ size_t ndr_size_string_array(const char **a, uint32_t count, libndr_flags flags)
850
42.8k
{
851
42.8k
  uint32_t i;
852
42.8k
  size_t size = 0;
853
42.8k
  int rawbytes = 0;
854
855
42.8k
  if (flags & LIBNDR_FLAG_STR_RAW8) {
856
0
    rawbytes = 1;
857
0
    flags &= ~LIBNDR_FLAG_STR_RAW8;
858
0
  }
859
860
42.8k
  switch (flags & LIBNDR_STRING_FLAGS) {
861
42.8k
  case LIBNDR_FLAG_STR_NULLTERM:
862
501k
    for (i = 0; i < count; i++) {
863
458k
      size += rawbytes?strlen(a[i]) + 1:strlen_m_term(a[i]);
864
458k
    }
865
42.8k
    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
0
    }
870
0
    break;
871
0
  default:
872
0
    return 0;
873
42.8k
  }
874
875
42.8k
  return size;
876
42.8k
}
877
878
/**
879
 * Return number of elements in a string including the last (zeroed) element
880
 */
881
_PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
882
0
{
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
0
}
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
static uint32_t ndr_string_n_length(const void *_var,
907
            size_t length,
908
            uint32_t element_size)
909
73.1k
{
910
73.1k
  size_t i = 0;
911
73.1k
  uint8_t zero[4] = {0,0,0,0};
912
73.1k
  const char *var = (const char *)_var;
913
73.1k
  int cmp;
914
915
73.1k
  if (element_size > 4) {
916
0
    return 0;
917
0
  }
918
919
10.9M
  for (i = 0; i < length; i++, var += element_size) {
920
10.9M
    cmp = memcmp(var, zero, element_size);
921
10.9M
    if (cmp == 0) {
922
33.4k
      break;
923
33.4k
    }
924
10.9M
  }
925
926
73.1k
  if (i == length) {
927
39.6k
    return length;
928
39.6k
  }
929
930
33.4k
  return i + 1;
931
73.1k
}
932
933
_PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
934
696k
{
935
696k
  uint32_t i;
936
696k
  uint32_t save_offset;
937
938
696k
  if (count == 0) {
939
5.11k
    return NDR_ERR_RANGE;
940
5.11k
  }
941
942
691k
  if (element_size && count - 1 > UINT32_MAX / element_size) {
943
1.47k
    return NDR_ERR_RANGE;
944
1.47k
  }
945
946
689k
  save_offset = ndr->offset;
947
689k
  NDR_CHECK(ndr_pull_advance(ndr, (count - 1) * element_size));
948
675k
  NDR_PULL_NEED_BYTES(ndr, element_size);
949
950
1.50M
  for (i = 0; i < element_size; i++) {
951
831k
    if (ndr->data[ndr->offset+i] != 0) {
952
887
      ndr->offset = save_offset;
953
954
887
      return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
955
887
    }
956
831k
  }
957
958
673k
  ndr->offset = save_offset;
959
960
673k
  return NDR_ERR_SUCCESS;
961
674k
}
962
963
_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
3.87M
{
965
3.87M
  size_t converted_size;
966
967
3.87M
  if (length == 0) {
968
2.19M
    *var = talloc_strdup(ndr->current_mem_ctx, "");
969
2.19M
    if (*var == NULL) {
970
0
      return ndr_pull_error(ndr, NDR_ERR_ALLOC,
971
0
                "Failed to talloc_strdup() in ndr_pull_charset()");
972
0
    }
973
2.19M
    return NDR_ERR_SUCCESS;
974
2.19M
  }
975
976
1.67M
  if (NDR_BE(ndr) && chset == CH_UTF16) {
977
121
    chset = CH_UTF16BE;
978
121
  }
979
980
1.67M
  if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
981
659
    return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
982
659
  }
983
1.67M
  NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
984
985
1.67M
  if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
986
1.67M
           ndr->data+ndr->offset, length*byte_mul,
987
1.67M
           var,
988
1.67M
           &converted_size))
989
7.66k
  {
990
7.66k
    return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
991
7.66k
              "Bad character conversion");
992
7.66k
  }
993
1.66M
  NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
994
995
1.66M
  return NDR_ERR_SUCCESS;
996
1.66M
}
997
998
_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
73.5k
{
1000
73.5k
  size_t converted_size;
1001
73.5k
  uint32_t str_len;
1002
1003
73.5k
  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
0
                "Failed to talloc_strdup() in ndr_pull_charset_to_null()");
1008
0
    }
1009
0
    return NDR_ERR_SUCCESS;
1010
0
  }
1011
1012
73.5k
  if (NDR_BE(ndr) && chset == CH_UTF16) {
1013
0
    chset = CH_UTF16BE;
1014
0
  }
1015
1016
73.5k
  if ((byte_mul != 0) && (length > UINT32_MAX/byte_mul)) {
1017
0
    return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "length overflow");
1018
0
  }
1019
73.5k
  NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
1020
1021
73.1k
  str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
1022
73.1k
  if (str_len == 0) {
1023
0
    return ndr_pull_error(ndr, NDR_ERR_LENGTH,
1024
0
              "Invalid length");
1025
0
  }
1026
1027
73.1k
  if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
1028
73.1k
           ndr->data+ndr->offset, str_len*byte_mul,
1029
73.1k
           var,
1030
73.1k
           &converted_size))
1031
40
  {
1032
40
    return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
1033
40
              "Bad character conversion");
1034
40
  }
1035
73.0k
  NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
1036
1037
73.0k
  return NDR_ERR_SUCCESS;
1038
73.0k
}
1039
1040
_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
1.47M
{
1042
1.47M
  size_t required;
1043
1044
1.47M
  if (NDR_BE(ndr) && chset == CH_UTF16) {
1045
0
    chset = CH_UTF16BE;
1046
0
  }
1047
1048
1.47M
  if ((byte_mul != 0) && (length > SIZE_MAX/byte_mul)) {
1049
0
    return ndr_push_error(ndr, NDR_ERR_LENGTH, "length overflow");
1050
0
  }
1051
1.47M
  required = byte_mul * length;
1052
1053
1.47M
  NDR_PUSH_NEED_BYTES(ndr, required);
1054
1055
1.47M
  if (required) {
1056
1.08M
    size_t size = 0;
1057
1058
1.08M
    if (var == NULL) {
1059
0
      return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
1060
0
    }
1061
1062
1.08M
    if (!convert_string(CH_UNIX, chset,
1063
1.08M
            var, strlen(var),
1064
1.08M
            ndr->data+ndr->offset, required, &size)) {
1065
196
      return ndr_push_error(ndr, NDR_ERR_CHARCNV,
1066
196
                "Bad character conversion");
1067
196
    }
1068
1069
    /* Make sure the remaining part of the string is filled with zeroes */
1070
1.08M
    if (size < required) {
1071
828k
      memset(ndr->data+ndr->offset+size, 0, required-size);
1072
828k
    }
1073
1.08M
  }
1074
1075
1.47M
  ndr->offset += required;
1076
1077
1.47M
  return NDR_ERR_SUCCESS;
1078
1.47M
}
1079
1080
_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
8.38k
{
1082
8.38k
  const char *str = var;
1083
1084
8.38k
  if (str == NULL) {
1085
0
    str = "\0"; /* i.e. two zero bytes, for UTF16 null word. */
1086
0
    length = 1;
1087
0
  }
1088
1089
8.38k
  return ndr_push_charset(ndr, ndr_flags, str, length, byte_mul, chset);
1090
8.38k
}
1091
1092
/* Return number of elements in a string in the specified charset */
1093
_PUBLIC_ uint32_t ndr_charset_length(const void *var, charset_t chset)
1094
1.01M
{
1095
1.01M
  switch (chset) {
1096
  /* case CH_UTF16: this has the same value as CH_UTF16LE */
1097
276k
  case CH_UTF16LE:
1098
276k
  case CH_UTF16BE:
1099
276k
  case CH_UTF16MUNGED:
1100
1.01M
  case CH_UTF8:
1101
1.01M
    return strlen_m_ext_term((const char *)var, CH_UNIX, chset);
1102
573
  case CH_DOS:
1103
573
  case CH_UNIX:
1104
573
    return strlen((const char *)var)+1;
1105
0
  default:
1106
    /* Fallback, this should never happen */
1107
0
    return strlen((const char *)var)+1;
1108
1.01M
  }
1109
1.01M
}