diff options
author | Matthias Dieter Wallnöfer <mdw@samba.org> | 2011-04-06 09:57:51 +0200 |
---|---|---|
committer | Matthias Dieter Wallnöfer <mdw@samba.org> | 2011-04-07 16:38:57 +0200 |
commit | 94f5b2f41346170fea90b4571f172df124139143 (patch) | |
tree | a6cfddfcf74b1281c1a44bf01297bd063c5f61b3 | |
parent | df9d46a353da15f68d299498f36ab0474c8e1e5a (diff) | |
download | samba-94f5b2f41346170fea90b4571f172df124139143.tar.gz samba-94f5b2f41346170fea90b4571f172df124139143.tar.bz2 samba-94f5b2f41346170fea90b4571f172df124139143.zip |
ldb:ldb_msg.c - make "ldb_msg_find_attr_as_*" more robust against invalid values
- Integer handling was modeled after validate code from "schema_syntax.c".
- Double handling was modeled similar, but with a dynamic buffer.
I don't know if there is a maximum literal length for double values but an
allocation shouldn't a problem here since doubles are rare.
- String handlind is enhanced with a terminating "0" test for safety.
Reviewed-by: abartlet + metze
Autobuild-User: Matthias Dieter Wallnöfer <mdw@samba.org>
Autobuild-Date: Thu Apr 7 16:38:57 CEST 2011 on sn-devel-104
-rw-r--r-- | source4/lib/ldb/common/ldb_msg.c | 125 |
1 files changed, 106 insertions, 19 deletions
diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 8060476d7d..9c5a279b8a 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -391,30 +391,63 @@ int ldb_msg_find_attr_as_int(const struct ldb_message *msg, int default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-2147483648")]; + char *end = NULL; + int ret; + if (!v || !v->data) { return default_value; } - return strtol((const char *)v->data, NULL, 0); + + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; + } + + memcpy(buf, v->data, v->length); + errno = 0; + ret = (int) strtoll(buf, &end, 10); + if (errno != 0) { + return default_value; + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; } -unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg, +unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg, const char *attr_name, unsigned int default_value) { - unsigned int ret; const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-2147483648")]; + char *end = NULL; + unsigned int ret; + if (!v || !v->data) { return default_value; } - /* in LDAP there're only int32_t values */ - errno = 0; - ret = strtol((const char *)v->data, NULL, 0); - if (errno == 0) { - return ret; + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; } - return strtoul((const char *)v->data, NULL, 0); + memcpy(buf, v->data, v->length); + errno = 0; + ret = (unsigned int) strtoll(buf, &end, 10); + if (errno != 0) { + errno = 0; + ret = (unsigned int) strtoull(buf, &end, 10); + if (errno != 0) { + return default_value; + } + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; } int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg, @@ -422,30 +455,63 @@ int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg, int64_t default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-9223372036854775808")]; + char *end = NULL; + int64_t ret; + if (!v || !v->data) { return default_value; } - return strtoll((const char *)v->data, NULL, 0); + + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; + } + + memcpy(buf, v->data, v->length); + errno = 0; + ret = (int64_t) strtoll(buf, &end, 10); + if (errno != 0) { + return default_value; + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; } -uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg, +uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg, const char *attr_name, uint64_t default_value) { - uint64_t ret; const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char buf[sizeof("-9223372036854775808")]; + char *end = NULL; + uint64_t ret; + if (!v || !v->data) { return default_value; } - /* in LDAP there're only int64_t values */ - errno = 0; - ret = strtoll((const char *)v->data, NULL, 0); - if (errno == 0) { - return ret; + ZERO_STRUCT(buf); + if (v->length >= sizeof(buf)) { + return default_value; } - return strtoull((const char *)v->data, NULL, 0); + memcpy(buf, v->data, v->length); + errno = 0; + ret = (uint64_t) strtoll(buf, &end, 10); + if (errno != 0) { + errno = 0; + ret = (uint64_t) strtoull(buf, &end, 10); + if (errno != 0) { + return default_value; + } + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; } double ldb_msg_find_attr_as_double(const struct ldb_message *msg, @@ -453,10 +519,28 @@ double ldb_msg_find_attr_as_double(const struct ldb_message *msg, double default_value) { const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); + char *buf; + char *end = NULL; + double ret; + if (!v || !v->data) { return default_value; } - return strtod((const char *)v->data, NULL); + buf = talloc_strndup(msg, (const char *)v->data, v->length); + if (buf == NULL) { + return default_value; + } + + errno = 0; + ret = strtod(buf, &end); + talloc_free(buf); + if (errno != 0) { + return default_value; + } + if (end && end[0] != '\0') { + return default_value; + } + return ret; } int ldb_msg_find_attr_as_bool(const struct ldb_message *msg, @@ -484,6 +568,9 @@ const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg, if (!v || !v->data) { return default_value; } + if (v->data[v->length] != '\0') { + return default_value; + } return (const char *)v->data; } |