summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2019-12-16 15:50:17 +0100
committerAndrew Bartlett <abartlet@samba.org>2019-12-20 07:35:41 +0000
commitf11e207e01c52566c47e350ff240fe95392de0c3 (patch)
tree41db2ac35dcf7b265e5c54adece51b2268c142c6 /librpc
parent0bd479140c18ab79479ced4f25f366744c3afe18 (diff)
downloadsamba-f11e207e01c52566c47e350ff240fe95392de0c3.tar.gz
librpc: Fix string length checking in ndr_pull_charset_to_null()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14219 Pair-Programmed-With: Guenther Deschner <gd@samba.org> Signed-off-by: Guenther Deschner <gd@samba.org> Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'librpc')
-rw-r--r--librpc/ndr/ndr_string.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c
index eb0af57a6ab..25f211b2ad3 100644
--- a/librpc/ndr/ndr_string.c
+++ b/librpc/ndr/ndr_string.c
@@ -560,6 +560,47 @@ _PUBLIC_ uint32_t ndr_string_length(const void *_var, uint32_t element_size)
return i+1;
}
+/**
+ * @brief Get the string length including the null terminator if available.
+ *
+ * This checks the string length based on the elements. The returned number
+ * includes the terminating null byte(s) if found.
+ *
+ * @param[in] _var The string the calculate the length for.
+ *
+ * @param[in] length The length of the buffer passed by _var.
+ *
+ * @param[in] element_size The element_size of a string char in bytes.
+ *
+ * @return The length of the strings or 0.
+ */
+static uint32_t ndr_string_n_length(const void *_var,
+ size_t length,
+ uint32_t element_size)
+{
+ size_t i = 0;
+ uint8_t zero[4] = {0,0,0,0};
+ const char *var = (const char *)_var;
+ int cmp;
+
+ if (element_size > 4) {
+ return 0;
+ }
+
+ for (i = 0; i < length; i++, var += element_size) {
+ cmp = memcmp(var, zero, element_size);
+ if (cmp == 0) {
+ break;
+ }
+ }
+
+ if (i == length) {
+ return length;
+ }
+
+ return i + 1;
+}
+
_PUBLIC_ enum ndr_err_code ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
{
uint32_t i;
@@ -629,8 +670,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_charset_to_null(struct ndr_pull *ndr, int nd
NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
- str_len = ndr_string_length(ndr->data+ndr->offset, byte_mul);
- str_len = MIN(str_len, length); /* overrun protection */
+ str_len = ndr_string_n_length(ndr->data+ndr->offset, length, byte_mul);
+ if (str_len == 0) {
+ return ndr_pull_error(ndr, NDR_ERR_LENGTH,
+ "Invalid length");
+ }
+
if (!convert_string_talloc(ndr->current_mem_ctx, chset, CH_UNIX,
ndr->data+ndr->offset, str_len*byte_mul,
discard_const_p(void *, var),