Skip to content

Commit a4c3ea2

Browse files
authored
Merge pull request github#9245 from ihsinme/ihsinme-patch-102
CPP: Add query for CWE-805: Buffer Access with Incorrect Length Value using some functions
2 parents 4eebeab + 1c35109 commit a4c3ea2

File tree

6 files changed

+140
-0
lines changed

6 files changed

+140
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
...
3+
char buf[256];
4+
X509_NAME_oneline(X509_get_subject_name(peer),buf,sizeof(buf)); // GOOD
5+
...
6+
char buf[256];
7+
X509_NAME_oneline(X509_get_subject_name(peer),buf,1024); // BAD
8+
...
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Using a size argument that is larger than the buffer size will result in an out-of-bounds memory access and possibly overflow. You need to limit the value of the length argument.</p>
7+
8+
</overview>
9+
10+
<example>
11+
<p>The following example shows the use of a function with and without an error in the size argument.</p>
12+
<sample src="BufferAccessWithIncorrectLengthValue.cpp" />
13+
14+
</example>
15+
<references>
16+
17+
<li>
18+
CERT Coding Standard:
19+
<a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR38-C.+Guarantee+that+library+functions+do+not+form+invalid+pointers">ARR38-C. Guarantee that library functions do not form invalid pointers - SEI CERT C Coding Standard - Confluence</a>.
20+
</li>
21+
22+
</references>
23+
</qhelp>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* @name Buffer access with incorrect length value
3+
* @description Incorrect use of the length argument in some functions will result in out-of-memory accesses.
4+
* @kind problem
5+
* @id cpp/buffer-access-with-incorrect-length-value
6+
* @problem.severity warning
7+
* @precision medium
8+
* @tags correctness
9+
* security
10+
* experimental
11+
* external/cwe/cwe-805
12+
*/
13+
14+
import cpp
15+
16+
/** Holds for a function `f`, which has an argument at index `bpos` that points to a buffer and an argument at index `spos` that points to a size. */
17+
predicate numberArgument(Function f, int bpos, int spos) {
18+
f.hasGlobalOrStdName([
19+
"X509_NAME_oneline", "SSL_CIPHER_description", "SSL_get_shared_ciphers",
20+
"SSL_export_keying_material_early", "SSL_export_keying_material", "SSL_set_alpn_protos",
21+
"SSL_CTX_set_alpn_protos", "SSL_read", "SSL_read_ex", "SSL_read_early_data",
22+
"SSL_bytes_to_cipher_list", "SSL_write", "SSL_SESSION_set1_master_key",
23+
"SSL_CTX_set_session_id_context", "BIO_gets", "BIO_read", "BIO_read_ex", "BIO_write",
24+
"BIO_write_ex", "BIO_ctrl", "BN_bn2binpad", "BN_signed_bn2bin", "BN_signed_bn2lebin",
25+
"EVP_PKEY_get_default_digest_name", "EVP_DigestUpdate", "EVP_PKEY_CTX_set1_tls1_prf_secret",
26+
"EVP_KDF_derive", "EVP_CIPHER_CTX_get_updated_iv", "EVP_PKEY_get_group_name", "EVP_MAC_init",
27+
"write", "read", "send", "sendto", "recv", "recvfrom", "strerror_r"
28+
]) and
29+
bpos = 1 and
30+
spos = 2
31+
or
32+
f.hasGlobalOrStdName(["X509_NAME_get_text_by_NID", "EVP_PKEY_get_utf8_string_param"]) and
33+
bpos = 2 and
34+
spos = 3
35+
or
36+
f.hasGlobalOrStdName([
37+
"BIO_snprintf", "BN_signed_lebin2bn", "BIO_new_mem_buf", "BN_lebin2bn", "BN_bin2bn",
38+
"EVP_read_pw_string", "EVP_read_pw_string", "strftime", "strnlen", "fgets", "snprintf",
39+
"vsnprintf"
40+
]) and
41+
bpos = 0 and
42+
spos = 1
43+
or
44+
f.hasGlobalOrStdName(["AES_ige_encrypt", "memchr"]) and bpos = 0 and spos = 2
45+
or
46+
f.hasGlobalOrStdName("EVP_MAC_final") and bpos = 1 and spos = 3
47+
or
48+
f.hasGlobalOrStdName("OBJ_obj2txt") and bpos = 2 and spos = 1
49+
or
50+
f.hasGlobalOrStdName("EVP_CIPHER_CTX_ctrl") and bpos = 3 and spos = 2
51+
or
52+
f.hasGlobalOrStdName(["EVP_PKEY_get_octet_string_param", "getnameinfo"]) and bpos = 2 and spos = 3
53+
or
54+
f.hasGlobalOrStdName([
55+
"EVP_DecryptUpdate", "EVP_EncryptUpdate", "EVP_PKEY_encrypt", "EVP_PKEY_sign",
56+
"EVP_CipherUpdate"
57+
]) and
58+
bpos = 3 and
59+
spos = 4
60+
or
61+
f.hasGlobalOrStdName("getnameinfo") and bpos = 4 and spos = 5
62+
}
63+
64+
from FunctionCall fc
65+
where
66+
exists(ArrayType array, int bufArgPos, int sizeArgPos |
67+
numberArgument(fc.getTarget(), bufArgPos, sizeArgPos) and
68+
fc.getArgument(pragma[only_bind_into](sizeArgPos)).getValue().toInt() > array.getByteSize() and
69+
fc.getArgument(pragma[only_bind_into](bufArgPos))
70+
.(VariableAccess)
71+
.getTarget()
72+
.getADeclarationEntry()
73+
.getType() = array
74+
)
75+
select fc,
76+
"Access beyond the bounds of the allocated memory is possible, the size argument used is greater than the size of the buffer."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.cpp:27:5:27:21 | call to X509_NAME_oneline | Access beyond the bounds of the allocated memory is possible, the size argument used is greater than the size of the buffer. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE/CWE-805/BufferAccessWithIncorrectLengthValue.ql
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
struct X509_NAME {};
2+
struct SSL {};
3+
struct X509 {};
4+
5+
char * X509_NAME_oneline(X509_NAME *a,char *buf,int size);
6+
X509 *SSL_get_peer_certificate(const SSL *ssl);
7+
X509_NAME *X509_get_subject_name(const X509 *x);
8+
char *strcasestr(char *a, char *b);
9+
10+
bool goodTest1(SSL *ssl,char *text)
11+
{
12+
X509 *peer;
13+
char buf[256];
14+
if( peer = SSL_get_peer_certificate(ssl))
15+
{
16+
X509_NAME_oneline(X509_get_subject_name(peer),buf,sizeof(buf)); // GOOD
17+
if((char*)strcasestr(buf,text)) return true;
18+
}
19+
return false;
20+
}
21+
bool badTest1(SSL *ssl,char *text)
22+
{
23+
X509 *peer;
24+
char buf[256];
25+
if( peer = SSL_get_peer_certificate(ssl))
26+
{
27+
X509_NAME_oneline(X509_get_subject_name(peer),buf,1024); // BAD
28+
if((char*)strcasestr(buf,text)) return true;
29+
}
30+
return false;
31+
}

0 commit comments

Comments
 (0)