summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Dieter Wallnöfer <mdw@samba.org>2011-04-06 09:57:51 +0200
committerMatthias Dieter Wallnöfer <mdw@samba.org>2011-04-07 16:38:57 +0200
commit94f5b2f41346170fea90b4571f172df124139143 (patch)
treea6cfddfcf74b1281c1a44bf01297bd063c5f61b3
parentdf9d46a353da15f68d299498f36ab0474c8e1e5a (diff)
downloadsamba-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.c125
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;
}