|
| 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." |
0 commit comments