2 Unix SMB/CIFS implementation.
4 routines for marshalling/unmarshalling string types
6 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
23 #include "librpc/ndr/libndr.h"
26 pull a general string from the wire
28 _PUBLIC_
enum ndr_err_code
ndr_pull_string(struct ndr_pull
*ndr
, ndr_flags_type ndr_flags
, const char **s
)
31 uint32_t len1
, ofs
, len2
;
33 size_t conv_src_len
= 0, converted_size
;
34 int do_convert
= 1, chset
= CH_UTF16
;
35 unsigned byte_mul
= 2;
36 libndr_flags flags
= ndr
->flags
;
37 unsigned c_len_term
= 0;
39 if (!(ndr_flags
& NDR_SCALARS
)) {
40 return NDR_ERR_SUCCESS
;
48 * We will check this flag, but from the unmodified
49 * ndr->flags, so just remove it from flags
51 flags
&= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL
;
53 switch (flags
& LIBNDR_ENCODING_FLAGS
) {
57 case LIBNDR_FLAG_STR_ASCII
:
62 case LIBNDR_FLAG_STR_UTF8
:
67 case LIBNDR_FLAG_STR_RAW8
:
73 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%"PRI_LIBNDR_FLAGS
"\n",
74 ndr
->flags
& LIBNDR_STRING_FLAGS
);
76 flags
&= ~LIBNDR_ENCODING_FLAGS
;
78 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
79 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
81 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
84 switch (flags
& LIBNDR_STRING_FLAGS
) {
85 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
86 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
87 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
88 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
90 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
);
93 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len2
));
95 return ndr_pull_error(ndr
, NDR_ERR_STRING
,
96 "Bad string lengths len1=%"PRIu32
" ofs=%"PRIu32
" len2=%"PRIu32
"\n",
98 } else if (len1
!= len2
) {
99 DEBUG(6,("len1[%"PRIu32
"] != len2[%"PRIu32
"]\n", len1
, len2
));
101 conv_src_len
= len2
+ c_len_term
;
104 case LIBNDR_FLAG_STR_SIZE4
:
105 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
106 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
107 conv_src_len
= len1
+ c_len_term
;
110 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
111 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
113 byte_mul
= 1; /* the length is now absolute */
116 case LIBNDR_FLAG_STR_LEN4
:
117 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
118 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
120 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
);
123 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
124 conv_src_len
= len1
+ c_len_term
;
127 case LIBNDR_FLAG_STR_SIZE2
:
128 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
:
129 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
130 conv_src_len
= len3
+ c_len_term
;
133 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
134 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
136 byte_mul
= 1; /* the length is now absolute */
139 case LIBNDR_FLAG_STR_NULLTERM
:
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
146 NDR_PULL_NEED_BYTES(ndr
, 1);
147 conv_src_len
= ascii_len_n((const char *)(ndr
->data
+ndr
->offset
), ndr
->data_size
- ndr
->offset
);
149 NDR_PULL_NEED_BYTES(ndr
, 2);
150 conv_src_len
= utf16_null_terminated_len_n(ndr
->data
+ndr
->offset
, ndr
->data_size
- ndr
->offset
);
152 byte_mul
= 1; /* the length is now absolute */
155 case LIBNDR_FLAG_STR_NOTERM
:
156 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
157 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
);
160 conv_src_len
= ndr
->data_size
- ndr
->offset
;
161 byte_mul
= 1; /* the length is now absolute */
165 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%"PRI_LIBNDR_FLAGS
"\n",
166 ndr
->flags
& LIBNDR_STRING_FLAGS
);
169 NDR_PULL_NEED_BYTES(ndr
, conv_src_len
* byte_mul
);
170 if (conv_src_len
== 0) {
171 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
174 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
,
175 "Failed to talloc_strndup() in zero-length ndr_pull_string()");
179 as
= talloc_strndup(ndr
->current_mem_ctx
,
180 (char *)ndr
->data
+ ndr
->offset
,
183 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
,
184 "Failed to talloc_strndup() in RAW8 ndr_pull_string()");
186 converted_size
= MIN(strlen(as
)+1, conv_src_len
);
187 } else if (!convert_string_talloc(ndr
->current_mem_ctx
, chset
,
188 CH_UNIX
, ndr
->data
+ ndr
->offset
,
189 conv_src_len
* byte_mul
,
192 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
193 "Bad character conversion with flags 0x%"PRI_LIBNDR_FLAGS
, flags
);
197 /* this is a way of detecting if a string is sent with the wrong
199 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
200 if (converted_size
> 0 && as
[converted_size
-1] == '\0') {
201 DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as
));
204 * We check the original ndr->flags as it has already
205 * been removed from the local variable flags
207 if (ndr
->flags
& LIBNDR_FLAG_STR_NO_EMBEDDED_NUL
) {
208 size_t strlen_of_unix_string
= strlen(as
);
209 if (strlen_of_unix_string
!= converted_size
) {
210 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
211 "Embedded NUL at position %zu in "
213 "(and therefore source string) "
215 "LIBNDR_FLAG_STR_NO_EMBEDDED_NUL\n",
216 strlen_of_unix_string
);
221 * We check the original ndr->flags as it has already
222 * been removed from the local variable flags
224 if (ndr
->flags
& LIBNDR_FLAG_STR_NO_EMBEDDED_NUL
) {
225 size_t strlen_of_unix_string
= strlen(as
);
226 if (converted_size
> 0 && strlen_of_unix_string
!= converted_size
- 1) {
227 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
228 "Embedded NUL at position %zu in "
230 "(and therefore source string) "
232 "LIBNDR_FLAG_STR_NO_EMBEDDED_NUL\n",
233 strlen_of_unix_string
);
236 if (converted_size
> 0 && as
[converted_size
-1] != '\0') {
237 DEBUG(6,("long string '%s', sent without NULL termination (which was expected)\n", as
));
241 NDR_CHECK(ndr_pull_advance(ndr
, conv_src_len
* byte_mul
));
244 return NDR_ERR_SUCCESS
;
249 push a general string onto the wire
251 _PUBLIC_
enum ndr_err_code
ndr_push_string(struct ndr_push
*ndr
, ndr_flags_type ndr_flags
, const char *s
)
253 ssize_t s_len
, c_len
;
255 int do_convert
= 1, chset
= CH_UTF16
;
256 libndr_flags flags
= ndr
->flags
;
257 unsigned byte_mul
= 2;
258 const uint8_t *dest
= NULL
;
259 uint8_t *dest_to_free
= NULL
;
260 static const uint8_t null_byte
[] = {0};
261 enum ndr_err_code ndr_err
= NDR_ERR_SUCCESS
;
263 if (!(ndr_flags
& NDR_SCALARS
)) {
264 return NDR_ERR_SUCCESS
;
271 s_len
= s
?strlen(s
):0;
274 * We will check this flag, but from the unmodified
275 * ndr->flags, so just remove it from flags
277 flags
&= ~LIBNDR_FLAG_STR_NO_EMBEDDED_NUL
;
279 switch (flags
& LIBNDR_ENCODING_FLAGS
) {
283 case LIBNDR_FLAG_STR_ASCII
:
288 case LIBNDR_FLAG_STR_UTF8
:
293 case LIBNDR_FLAG_STR_RAW8
:
299 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%"PRI_LIBNDR_FLAGS
"\n",
300 ndr
->flags
& LIBNDR_STRING_FLAGS
);
302 flags
&= ~LIBNDR_ENCODING_FLAGS
;
304 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
306 if (!(flags
& LIBNDR_FLAG_STR_NOTERM
)) {
313 } else if (!do_convert
) {
315 dest
= (const uint8_t *)s
;
319 ok
= convert_string_talloc(ndr
, CH_UNIX
, chset
, s
, s_len
,
320 &dest_to_free
, &d_len
);
322 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
323 "Bad character push conversion with flags 0x%"PRI_LIBNDR_FLAGS
, flags
);
329 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
331 flags
&= ~LIBNDR_FLAG_STR_BYTESIZE
;
332 } else if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
333 c_len
= (d_len
/ byte_mul
)-1;
334 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
336 c_len
= d_len
/ byte_mul
;
339 switch (flags
& LIBNDR_STRING_FLAGS
) {
340 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
341 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
342 ndr_err
= ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
);
343 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
346 ndr_err
= ndr_push_uint32(ndr
, NDR_SCALARS
, 0);
347 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
350 ndr_err
= ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
);
351 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
354 ndr_err
= ndr_push_bytes(ndr
, dest
, d_len
);
355 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
360 case LIBNDR_FLAG_STR_LEN4
:
361 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
362 ndr_err
= ndr_push_uint32(ndr
, NDR_SCALARS
, 0);
363 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
366 ndr_err
= ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
);
367 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
370 ndr_err
= ndr_push_bytes(ndr
, dest
, d_len
);
371 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
376 case LIBNDR_FLAG_STR_SIZE4
:
377 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
378 ndr_err
= ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
);
379 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
382 ndr_err
= ndr_push_bytes(ndr
, dest
, d_len
);
383 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
388 case LIBNDR_FLAG_STR_SIZE2
:
389 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
:
390 ndr_err
= ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
);
391 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
394 ndr_err
= ndr_push_bytes(ndr
, dest
, d_len
);
395 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
400 case LIBNDR_FLAG_STR_NULLTERM
:
401 ndr_err
= ndr_push_bytes(ndr
, dest
, d_len
);
402 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
408 if (ndr
->flags
& LIBNDR_FLAG_REMAINING
) {
409 ndr_err
= ndr_push_bytes(ndr
, dest
, d_len
);
410 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
416 ndr_err
= ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%"PRI_LIBNDR_FLAGS
"\n",
417 ndr
->flags
& LIBNDR_STRING_FLAGS
);
422 TALLOC_FREE(dest_to_free
);
427 push a general string onto the wire
429 _PUBLIC_
size_t ndr_string_array_size(struct ndr_push
*ndr
, const char *s
)
432 libndr_flags flags
= ndr
->flags
;
433 unsigned byte_mul
= 2;
434 unsigned c_len_term
= 1;
436 if (flags
& LIBNDR_FLAG_STR_RAW8
) {
437 c_len
= s
?strlen(s
):0;
439 c_len
= s
?strlen_m(s
):0;
442 if (flags
& (LIBNDR_FLAG_STR_ASCII
|LIBNDR_FLAG_STR_RAW8
|LIBNDR_FLAG_STR_UTF8
)) {
446 if (flags
& LIBNDR_FLAG_STR_NOTERM
) {
450 c_len
= c_len
+ c_len_term
;
452 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
453 c_len
= c_len
* byte_mul
;
459 _PUBLIC_
void ndr_print_string(struct ndr_print
*ndr
, const char *name
, const char *s
)
461 if (NDR_HIDE_SECRET(ndr
)) {
462 ndr
->print(ndr
, "%-25s: <REDACTED SECRET VALUE>", name
);
466 ndr
->print(ndr
, "%-25s: '%s'", name
, s
);
468 ndr
->print(ndr
, "%-25s: NULL", name
);
472 _PUBLIC_
uint32_t ndr_size_string(int ret
, const char * const* string
, ndr_flags_type flags
)
474 /* FIXME: Is this correct for all strings ? */
475 if(!(*string
)) return ret
;
476 return ret
+strlen(*string
)+1;
480 pull a UTF‐16 string from the wire
482 _PUBLIC_
enum ndr_err_code
ndr_pull_u16string(struct ndr_pull
*ndr
,
483 ndr_flags_type ndr_flags
,
484 const unsigned char **s
)
486 unsigned char *as
= NULL
;
487 const char *const src_str
= (char *)ndr
->data
+ ndr
->offset
;
490 if (!(ndr_flags
& NDR_SCALARS
)) {
491 return NDR_ERR_SUCCESS
;
496 * It isn’t clear how this type should be encoded in a
497 * big‐endian context.
499 return ndr_pull_error(
502 "u16string does not support big‐endian encoding\n");
505 if (ndr
->flags
& LIBNDR_ENCODING_FLAGS
) {
506 return ndr_pull_error(
509 "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
510 " passed to ndr_pull_u16string()\n",
511 ndr
->flags
& LIBNDR_STRING_FLAGS
);
514 switch (ndr
->flags
& LIBNDR_STRING_FLAGS
) {
515 case LIBNDR_FLAG_STR_NULLTERM
:
517 * We ensure that src_len cannot equal 0 by
518 * requiring that there be enough bytes for at least
519 * the NULL terminator
521 NDR_PULL_NEED_BYTES(ndr
, 2);
522 src_len
= utf16_null_terminated_len_n(src_str
,
528 return ndr_pull_error(
531 "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
532 " passed to ndr_pull_u16string()\n",
533 ndr
->flags
& LIBNDR_STRING_FLAGS
);
536 NDR_PULL_NEED_BYTES(ndr
, src_len
);
537 as
= talloc_utf16_strlendup(ndr
->current_mem_ctx
,
541 return ndr_pull_error(ndr
,
543 "Failed to talloc_utf16_strlendup() in "
544 "ndr_pull_u16string()");
547 NDR_CHECK(ndr_pull_advance(ndr
, src_len
));
550 return NDR_ERR_SUCCESS
;
554 push a UTF‐16 string onto the wire
556 _PUBLIC_
enum ndr_err_code
ndr_push_u16string(struct ndr_push
*ndr
,
557 ndr_flags_type ndr_flags
,
558 const unsigned char *s
)
562 if (!(ndr_flags
& NDR_SCALARS
)) {
563 return NDR_ERR_SUCCESS
;
568 * It isn’t clear how this type should be encoded in a
569 * big‐endian context.
571 return ndr_push_error(
574 "u16string does not support big‐endian encoding\n");
578 return ndr_push_error(
580 NDR_ERR_INVALID_POINTER
,
581 "NULL pointer passed to ndr_push_u16string()");
584 s_len
= utf16_null_terminated_len(s
);
585 if (s_len
> UINT32_MAX
) {
586 return ndr_push_error(
589 "length overflow in ndr_push_u16string()");
592 if (ndr
->flags
& LIBNDR_ENCODING_FLAGS
) {
593 return ndr_push_error(
596 "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
597 " passed to ndr_push_u16string()\n",
598 ndr
->flags
& LIBNDR_STRING_FLAGS
);
601 switch (ndr
->flags
& LIBNDR_STRING_FLAGS
) {
602 case LIBNDR_FLAG_STR_NULLTERM
:
603 NDR_CHECK(ndr_push_bytes(ndr
, s
, s_len
));
607 if (ndr
->flags
& LIBNDR_FLAG_REMAINING
) {
608 NDR_CHECK(ndr_push_bytes(ndr
, s
, s_len
));
612 return ndr_push_error(
615 "Unsupported string flags 0x%" PRI_LIBNDR_FLAGS
616 " passed to ndr_push_u16string()\n",
617 ndr
->flags
& LIBNDR_STRING_FLAGS
);
620 return NDR_ERR_SUCCESS
;
623 _PUBLIC_
void ndr_print_u16string(struct ndr_print
*ndr
,
625 const unsigned char *s
)
627 return ndr_print_array_uint8(ndr
,
633 static uint32_t guess_string_array_size(struct ndr_pull
*ndr
, ndr_flags_type ndr_flags
)
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.
644 static enum ndr_err_code
extend_string_array(struct ndr_pull
*ndr
,
648 const char **a
= *_a
;
649 uint32_t inc
= *count
/ 4 + 3;
650 uint32_t alloc_size
= *count
+ inc
;
652 if (alloc_size
< *count
) {
654 return NDR_ERR_ALLOC
;
657 * We allocate and zero two more bytes than we report back, so that
658 * the string array will always be NULL terminated.
660 a
= talloc_realloc(ndr
->current_mem_ctx
, a
,
663 NDR_ERR_HAVE_NO_MEMORY(a
);
665 memset(a
+ *count
, 0, inc
* sizeof(a
[0]));
667 *count
= alloc_size
- 2;
668 return NDR_ERR_SUCCESS
;
672 pull a general string array from the wire
674 _PUBLIC_
enum ndr_err_code
ndr_pull_string_array(struct ndr_pull
*ndr
, ndr_flags_type ndr_flags
, const char ***_a
)
676 const char **a
= NULL
;
678 libndr_flags flags
= ndr
->flags
;
679 libndr_flags saved_flags
= ndr
->flags
;
682 if (!(ndr_flags
& NDR_SCALARS
)) {
683 return NDR_ERR_SUCCESS
;
686 alloc_size
= guess_string_array_size(ndr
, ndr_flags
);
687 a
= talloc_zero_array(ndr
->current_mem_ctx
, const char *, alloc_size
+ 2);
688 NDR_ERR_HAVE_NO_MEMORY(a
);
690 switch (flags
& (LIBNDR_FLAG_STR_NULLTERM
|LIBNDR_FLAG_STR_NOTERM
)) {
691 case LIBNDR_FLAG_STR_NULLTERM
:
693 * here the strings are null terminated
694 * but also the array is null terminated if LIBNDR_FLAG_REMAINING
697 for (count
= 0;; count
++) {
699 const char *s
= NULL
;
700 if (count
== alloc_size
) {
701 NDR_CHECK(extend_string_array(ndr
,
706 tmp_ctx
= ndr
->current_mem_ctx
;
707 ndr
->current_mem_ctx
= a
;
708 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
709 ndr
->current_mem_ctx
= tmp_ctx
;
710 if ((ndr
->data_size
- ndr
->offset
) == 0 && ndr
->flags
& LIBNDR_FLAG_REMAINING
)
715 if (strcmp("", s
)==0) {
726 case LIBNDR_FLAG_STR_NOTERM
:
727 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
728 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
);
732 * here the strings are not null terminated
733 * but separated by a null terminator
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
739 * as LIBNDR_FLAG_STR_NULLTERM also end at the end
740 * of the buffer, we can pull each string with this flag
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
745 ndr
->flags
&= ~(LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_REMAINING
);
746 ndr
->flags
|= LIBNDR_FLAG_STR_NULLTERM
;
748 for (count
= 0; ((ndr
->data_size
- ndr
->offset
) > 0); count
++) {
750 const char *s
= NULL
;
751 if (count
== alloc_size
) {
752 NDR_CHECK(extend_string_array(ndr
,
757 tmp_ctx
= ndr
->current_mem_ctx
;
758 ndr
->current_mem_ctx
= a
;
759 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
760 ndr
->current_mem_ctx
= tmp_ctx
;
764 a
= talloc_realloc(ndr
->current_mem_ctx
, a
, const char *, count
+ 1);
765 NDR_ERR_HAVE_NO_MEMORY(a
);
770 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%"PRI_LIBNDR_FLAGS
"\n",
771 ndr
->flags
& LIBNDR_STRING_FLAGS
);
774 ndr
->flags
= saved_flags
;
775 return NDR_ERR_SUCCESS
;
779 push a general string array onto the wire
781 _PUBLIC_
enum ndr_err_code
ndr_push_string_array(struct ndr_push
*ndr
, ndr_flags_type ndr_flags
, const char **a
)
784 libndr_flags flags
= ndr
->flags
;
785 libndr_flags saved_flags
= ndr
->flags
;
787 if (!(ndr_flags
& NDR_SCALARS
)) {
788 return NDR_ERR_SUCCESS
;
791 switch (flags
& LIBNDR_STRING_FLAGS
) {
792 case LIBNDR_FLAG_STR_NULLTERM
:
793 for (count
= 0; a
&& a
[count
]; count
++) {
794 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
796 /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
797 if (!(flags
& LIBNDR_FLAG_REMAINING
))
799 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
803 case LIBNDR_FLAG_STR_NOTERM
:
804 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
805 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
);
809 for (count
= 0; a
&& a
[count
]; count
++) {
811 ndr
->flags
&= ~(LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_REMAINING
);
812 ndr
->flags
|= LIBNDR_FLAG_STR_NULLTERM
;
813 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
814 ndr
->flags
= saved_flags
;
816 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
822 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%"PRI_LIBNDR_FLAGS
"\n",
823 ndr
->flags
& LIBNDR_STRING_FLAGS
);
826 ndr
->flags
= saved_flags
;
827 return NDR_ERR_SUCCESS
;
830 _PUBLIC_
void ndr_print_string_array(struct ndr_print
*ndr
, const char *name
, const char **a
)
835 for (count
= 0; a
&& a
[count
]; count
++) {}
837 ndr
->print(ndr
, "%s: ARRAY(%"PRIu32
")", name
, count
);
839 for (i
=0;i
<count
;i
++) {
841 if (asprintf(&idx
, "[%"PRIu32
"]", i
) != -1) {
842 ndr_print_string(ndr
, idx
, a
[i
]);
849 _PUBLIC_
size_t ndr_size_string_array(const char **a
, uint32_t count
, libndr_flags flags
)
855 if (flags
& LIBNDR_FLAG_STR_RAW8
) {
857 flags
&= ~LIBNDR_FLAG_STR_RAW8
;
860 switch (flags
& LIBNDR_STRING_FLAGS
) {
861 case LIBNDR_FLAG_STR_NULLTERM
:
862 for (i
= 0; i
< count
; i
++) {
863 size
+= rawbytes
?strlen(a
[i
]) + 1:strlen_m_term(a
[i
]);
866 case LIBNDR_FLAG_STR_NOTERM
:
867 for (i
= 0; i
< count
; i
++) {
868 size
+= rawbytes
?strlen(a
[i
]):strlen_m(a
[i
]);
879 * Return number of elements in a string including the last (zeroed) element
881 _PUBLIC_
uint32_t ndr_string_length(const void *_var
, uint32_t element_size
)
884 uint8_t zero
[4] = {0,0,0,0};
885 const char *var
= (const char *)_var
;
887 for (i
= 0; memcmp(var
+i
*element_size
,zero
,element_size
) != 0; i
++);
893 * @brief Get the string length including the null terminator if available.
895 * This checks the string length based on the elements. The returned number
896 * includes the terminating null byte(s) if found.
898 * @param[in] _var The string to calculate the length for.
900 * @param[in] length The length of the buffer passed by _var.
902 * @param[in] element_size The element_size of a string char in bytes.
904 * @return The length of the strings or 0.
906 static uint32_t ndr_string_n_length(const void *_var
,
908 uint32_t element_size
)
911 uint8_t zero
[4] = {0,0,0,0};
912 const char *var
= (const char *)_var
;
915 if (element_size
> 4) {
919 for (i
= 0; i
< length
; i
++, var
+= element_size
) {
920 cmp
= memcmp(var
, zero
, element_size
);
933 _PUBLIC_
enum ndr_err_code
ndr_check_string_terminator(struct ndr_pull
*ndr
, uint32_t count
, uint32_t element_size
)
936 uint32_t save_offset
;
939 return NDR_ERR_RANGE
;
942 if (element_size
&& count
- 1 > UINT32_MAX
/ element_size
) {
943 return NDR_ERR_RANGE
;
946 save_offset
= ndr
->offset
;
947 NDR_CHECK(ndr_pull_advance(ndr
, (count
- 1) * element_size
));
948 NDR_PULL_NEED_BYTES(ndr
, element_size
);
950 for (i
= 0; i
< element_size
; i
++) {
951 if (ndr
->data
[ndr
->offset
+i
] != 0) {
952 ndr
->offset
= save_offset
;
954 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
, "String terminator not present or outside string boundaries");
958 ndr
->offset
= save_offset
;
960 return NDR_ERR_SUCCESS
;
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
)
965 size_t converted_size
;
968 *var
= talloc_strdup(ndr
->current_mem_ctx
, "");
970 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
,
971 "Failed to talloc_strdup() in ndr_pull_charset()");
973 return NDR_ERR_SUCCESS
;
976 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
980 if ((byte_mul
!= 0) && (length
> UINT32_MAX
/byte_mul
)) {
981 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
, "length overflow");
983 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
985 if (!convert_string_talloc(ndr
->current_mem_ctx
, chset
, CH_UNIX
,
986 ndr
->data
+ndr
->offset
, length
*byte_mul
,
990 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
991 "Bad character conversion");
993 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
995 return NDR_ERR_SUCCESS
;
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
)
1000 size_t converted_size
;
1004 *var
= talloc_strdup(ndr
->current_mem_ctx
, "");
1006 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
,
1007 "Failed to talloc_strdup() in ndr_pull_charset_to_null()");
1009 return NDR_ERR_SUCCESS
;
1012 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
1016 if ((byte_mul
!= 0) && (length
> UINT32_MAX
/byte_mul
)) {
1017 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
, "length overflow");
1019 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
1021 str_len
= ndr_string_n_length(ndr
->data
+ndr
->offset
, length
, byte_mul
);
1023 return ndr_pull_error(ndr
, NDR_ERR_LENGTH
,
1027 if (!convert_string_talloc(ndr
->current_mem_ctx
, chset
, CH_UNIX
,
1028 ndr
->data
+ndr
->offset
, str_len
*byte_mul
,
1032 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
1033 "Bad character conversion");
1035 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
1037 return NDR_ERR_SUCCESS
;
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
)
1044 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
1048 if ((byte_mul
!= 0) && (length
> SIZE_MAX
/byte_mul
)) {
1049 return ndr_push_error(ndr
, NDR_ERR_LENGTH
, "length overflow");
1051 required
= byte_mul
* length
;
1053 NDR_PUSH_NEED_BYTES(ndr
, required
);
1059 return ndr_push_error(ndr
, NDR_ERR_INVALID_POINTER
, "NULL [ref] pointer");
1062 if (!convert_string(CH_UNIX
, chset
,
1064 ndr
->data
+ndr
->offset
, required
, &size
)) {
1065 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
1066 "Bad character conversion");
1069 /* Make sure the remaining part of the string is filled with zeroes */
1070 if (size
< required
) {
1071 memset(ndr
->data
+ndr
->offset
+size
, 0, required
-size
);
1075 ndr
->offset
+= required
;
1077 return NDR_ERR_SUCCESS
;
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
)
1082 const char *str
= var
;
1085 str
= "\0"; /* i.e. two zero bytes, for UTF16 null word. */
1089 return ndr_push_charset(ndr
, ndr_flags
, str
, length
, byte_mul
, chset
);
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
)
1096 /* case CH_UTF16: this has the same value as CH_UTF16LE */
1099 case CH_UTF16MUNGED
:
1101 return strlen_m_ext_term((const char *)var
, CH_UNIX
, chset
);
1104 return strlen((const char *)var
)+1;
1106 /* Fallback, this should never happen */
1107 return strlen((const char *)var
)+1;