In several cases, snprintf result was used without validating its range.
When formatted string would overflow buffer or error happens, snprintf
will return either value larger than buffer size, or -1. In both cases,
if you add this value to pointer (or similar), bad things will happen.
Pattern to watch for: =.*snprintf
I have not verified if any of this is exploitable. In some cases, I was
not sure about proper error handling (watch for XXX comments).
While fixing this error, I noticed typo in Ip::Qos::Config::dumpConfigLine:
markMissMask was used instead of tosMissMask.
Patches compile-tested (however, only on linux/x86/gcc49 and in default
configuration).
Index: squid-3.5.13/src/ip/QosConfig.cc
===
--- squid-3.5.13.orig/src/ip/QosConfig.cc
+++ squid-3.5.13/src/ip/QosConfig.cc
@@ -392,7 +392,7 @@ Ip::Qos::Config::dumpConfigLine(char *en
if (tosMiss > 0) {
p += snprintf(p, 11, " miss=0x%02X", tosMiss);
if (tosMissMask!=0xFFU) {
-p += snprintf(p, 6, "/0x%02X", markMissMask);
+p += snprintf(p, 6, "/0x%02X", tosMissMask);
}
}
if (preserveMissTos == 0) {
Index: squid-3.5.13/helpers/digest_auth/file/text_backend.cc
===
--- squid-3.5.13.orig/helpers/digest_auth/file/text_backend.cc
+++ squid-3.5.13/helpers/digest_auth/file/text_backend.cc
@@ -171,7 +171,7 @@ GetPassword(RequestData * requestData)
if (!hash)
return NULL;
len = snprintf(buf, sizeof(buf), "%s:%s", requestData->user, requestData->realm);
-if (len >= static_cast(sizeof(buf)))
+if (len < 0 || len >= static_cast(sizeof(buf)))
return NULL;
u = (user_data*)hash_lookup(hash, buf);
if (u)
Index: squid-3.5.13/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc
===
--- squid-3.5.13.orig/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc
+++ squid-3.5.13/helpers/external_acl/eDirectory_userip/ext_edirectory_userip_acl.cc
@@ -227,7 +227,7 @@ local_printfx(const char *msg,...)
va_start(ap, msg);
x = vsnprintf(dbuf, sz, msg, ap);
va_end(ap);
-if (x > 0) {
+if (x > 0 || x >= sz) {
dbuf[x] = '\0';
++x;
fputs(dbuf, stdout);
@@ -879,6 +879,7 @@ ConvertIP(edui_ldap_t *l, char *ip)
return LDAP_ERR_OOB;/* Out of bounds -- Invalid address */
memset(hexc, '\0', sizeof(hexc));
int hlen = snprintf(hexc, sizeof(hexc), "%02X", (int)x);
+if (hlen < 0 || hlen >= static_cast(sizeof(hexc))) hlen = 0; /* impossible */
strncat(l->search_ip, hexc, hlen);
} else
break; /* reached end of octet */
@@ -1106,10 +1107,12 @@ SearchFilterLDAP(edui_ldap_t *l, char *g
if (l->status & LDAP_IPV4_S) {
int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \
bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
strncat(bufb, bufd, ln);
} else if (l->status & LDAP_IPV6_S) {
int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \
bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
strncat(bufb, bufd, ln);
} else
strncat(bufb, ")", 1);
@@ -1132,10 +1135,12 @@ SearchFilterLDAP(edui_ldap_t *l, char *g
if (l->status & LDAP_IPV4_S) {
int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \
bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
strncat(bufb, bufd, ln);
} else if (l->status & LDAP_IPV6_S) {
int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \
bufc, bufc);
+if (ln < 0 || ln >= static_cast(sizeof(bufd))) return LDAP_ERR_FAILED;
strncat(bufb, bufd, ln);
} else
strncat(bufb, ")", 1);
@@ -1278,6 +1283,7 @@ SearchIPLDAP(edui_ldap_t *l)
if (c < 0)
c = c + 256;
int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
+if (hlen < 0 || hlen >= static_cast(sizeof(hexc))) return LDAP_ERR_FAILED;
if (k == 0)
xstrncpy(bufb, hexc, sizeof(bufb));
else
@@ -1313,6 +