Skip to content

Instantly share code, notes, and snippets.

@scovetta
Created December 19, 2019 07:52
Show Gist options
  • Save scovetta/c6e759fbecf55f9d4f90a7c0229063fb to your computer and use it in GitHub Desktop.
Save scovetta/c6e759fbecf55f9d4f90a7c0229063fb to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# License: MIT
# Author: Michael Scovetta <michael.scovetta@gmail.com>
import re
import sys
"""
Usage:
Do an initial grep through the source tree and xargs the results over to this script, e.g.:
grep -FlRi 'alloc' freebsd_src | xargs -n1 -P6 python malloc.py
"""
"""
The MALLOCs here are malloc-like functions. You can find some of them with this:
egrep -hoRi "[a-z_]*alloc\s*\(" freebsd_src | sort | uniq -c | sort -n
"""
MALLOCS = ['malloc', 'realloc', 'alloc', 'xmalloc', 'os_malloc', 'os_zalloc', '_malloc', 'g_malloc']
if len(sys.argv) != 2:
print('Usage: python malloc_search.py filename')
sys.exit(1)
filename = sys.argv[1]
with open(filename) as f:
lines = map(str.strip, f)
for line_number, line in enumerate(lines):
for malloc in MALLOCS:
# First, we check to see if we match the general malloc pattern, with optional cast.
matches = re.match(r'.*(?:\((.+\s*\*)\)\s*)?' + malloc + r'\s*\((.+)\)\s*;$', line, re.IGNORECASE)
if not matches:
continue # Missing the initial malloc pattern
cast_param = matches.group(1)
if cast_param:
cast_param = cast_param.replace('*', '').strip()
malloc_params = matches.group(2)
sizeof_matches = re.search(r'sizeof\s*\(([^\)]+)\)', malloc_params)
if sizeof_matches:
sizeof_param = sizeof_matches.group(1)
else:
continue # Must have a sizeof operator
var_matches = re.search(r'([a-z][a-z0-9_]*)\s*\*\s*sizeof', malloc_params)
if not var_matches:
var_matches = re.search(r'sizeof\s*\([^\)]+\)\s*\*\s*([a-z][a-z0-9_]*)', malloc_params, re.IGNORECASE)
if not var_matches:
continue # We need a multiplicative offset
var_param = var_matches.group(1)
const_matches = re.match(r'.*(\+\s*\d+)\s*$', malloc_params)
if not const_matches:
const_matches = re.match(r'^\s*(\d+\s*\+).*', malloc_params)
if not const_matches:
continue # Must have a constant offset
const_param = const_matches.group(1)
print("************************")
print("Found a potential match:")
print(" Filename: {0}:{1}".format(filename, line_number))
print(" Offending Line: {0}".format(line))
print(" Variable assignments found at:")
for var_line_number, var_line in enumerate(lines):
if var_line_number >= line_number:
break # Only looking upward
if re.search(r'(^|\b)' + re.escape(var_param) + r'\s*=[^=]', var_line, re.IGNORECASE):
print("\t{0} {1}".format(var_line_number, var_line))
print(" Variable usage found at:")
for var_line_number, var_line in enumerate(lines):
if var_line_number >= line_number:
break # Only looking upward
if var_param in var_line:
print("\t{0} {1}".format(var_line_number + 1, var_line))
print("")
break
@scovetta
Copy link
Author

Results from running against github.com/freebsd/freebsd/tree/master

************************
Found a potential match:
 Filename: freebsd/contrib/binutils/libiberty/argv.c:412
 Offending Line: buffer = (char *) xmalloc (pos * sizeof (char) + 1);
 Variable assignments found at:
        407 pos = ftell (f);
 Variable usage found at:
        142 If the input is a null string (as opposed to a @code{NULL} pointer),
        386 long pos;
        408 pos = ftell (f);
        409 if (pos == -1)

************************
Found a potential match:
 Filename: freebsd/contrib/gcclibs/libiberty/argv.c:359
 Offending Line: buffer = (char *) xmalloc (pos * sizeof (char) + 1);
 Variable assignments found at:
        354 pos = ftell (f);
 Variable usage found at:
        142 If the input is a null string (as opposed to a @code{NULL} pointer),
        333 long pos;
        355 pos = ftell (f);
        356 if (pos == -1)

************************
Found a potential match:
 Filename: freebsd/contrib/sqlite3/shell.c:6970
 Offending Line: pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
 Variable assignments found at:
        6967 int nColl = STRLEN(zColl);
 Variable usage found at:
        6968 int nColl = STRLEN(zColl);

************************
Found a potential match:
 Filename: freebsd/contrib/subversion/subversion/libsvn_subr/utf8proc/utf8proc.c:708
 Offending Line: buffer = (utf8proc_int32_t *) malloc(result * sizeof(utf8proc_int32_t) + 1);
 Variable assignments found at:
        706 result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data);
 Variable usage found at:
        245 and are thus not handled by this function. This may result in an incorrect break before
        506 utf8proc_ssize_t decomp_result;
        524 decomp_result = utf8proc_decompose_char(
        528 if (decomp_result < 0) return decomp_result;
        529 wpos += decomp_result;
        705 utf8proc_ssize_t result;
        707 result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data);
        708 if (result < 0) return result;

************************
Found a potential match:
 Filename: freebsd/contrib/subversion/subversion/libsvn_subr/win32_crashrpt.c:71
 Offending Line: char *utf8_str = malloc(sizeof(wchar_t) * len + 1);
 Variable assignments found at:
        70 size_t len = wcslen(str);
 Variable usage found at:
        71 size_t len = wcslen(str);

************************
Found a potential match:
 Filename: freebsd/contrib/unbound/validator/autotrust.c:169
 Offending Line: char* comment = (char*) malloc(sizeof(char)*len+1);
 Variable assignments found at:
        168 int len = (int)strlen(str), pos = 0, timestamp = 0;
 Variable usage found at:
        125 return (int)(pos-str)+(int)strlen(sub);
        147 char* str = sldns_wire2str_dname(ta->rr, ta->dname_len);
        149 ta->rr, ta->rr_len, ta->dname_len),
        150 sldns_wirerr_get_rdatalen(ta->rr, ta->rr_len,
        151 ta->dname_len));
        169 int len = (int)strlen(str), pos = 0, timestamp = 0;

************************
Found a potential match:
 Filename: freebsd/usr.bin/sdiff/sdiff.c:263
 Offending Line: diffargv[1]  = realloc(diffargv[1], sizeof(char) * strlen(diffargv[1]) + 2);
 Variable assignments found at:
 Variable usage found at:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment