Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-90110: Fix the c-analyzer Tool #102483

Merged
merged 16 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Include/internal/pycore_global_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct _Py_interp_static_objects {
// hamt_empty is here instead of global because of its weakreflist.
_PyGC_Head_UNUSED _hamt_empty_gc_not_used;
PyHamtObject hamt_empty;
PyBaseExceptionObject last_resort_memory_error;
} singletons;
};

Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);

extern instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
extern instrinsic_func2 _PyIntrinsics_BinaryFunctions[];
extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[];

6 changes: 6 additions & 0 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ extern "C" {
#include "pycore_obmalloc_init.h"


extern PyTypeObject _PyExc_MemoryError;


/* The static initializers defined here should only be used
in the runtime init code (in pystate.c and pylifecycle.c). */

Expand Down Expand Up @@ -120,6 +123,9 @@ extern "C" {
.ob_base = _PyObject_IMMORTAL_INIT(&_PyHamt_Type), \
.h_root = (PyHamtNode*)&_Py_SINGLETON(hamt_bitmap_node_empty), \
}, \
.last_resort_memory_error = { \
_PyObject_IMMORTAL_INIT(&_PyExc_MemoryError), \
}, \
}, \
}, \
._initial_thread = _PyThreadState_INIT, \
Expand Down
13 changes: 4 additions & 9 deletions Objects/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -3207,16 +3207,16 @@ SimpleExtendsException(PyExc_Exception, ReferenceError,

#define MEMERRORS_SAVE 16

static PyBaseExceptionObject last_resort_memory_error;

static PyObject *
get_memory_error(int allow_allocation, PyObject *args, PyObject *kwds)
{
PyBaseExceptionObject *self;
struct _Py_exc_state *state = get_exc_state();
if (state->memerrors_freelist == NULL) {
if (!allow_allocation) {
return Py_NewRef(&last_resort_memory_error);
PyInterpreterState *interp = _PyInterpreterState_GET();
return Py_NewRef(
&_Py_INTERP_SINGLETON(interp, last_resort_memory_error));
}
PyObject *result = BaseException_new((PyTypeObject *)PyExc_MemoryError, args, kwds);
return result;
Expand All @@ -3239,8 +3239,6 @@ get_memory_error(int allow_allocation, PyObject *args, PyObject *kwds)
return (PyObject *)self;
}

static PyBaseExceptionObject last_resort_memory_error;

static PyObject *
MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
Expand Down Expand Up @@ -3325,7 +3323,7 @@ free_preallocated_memerrors(struct _Py_exc_state *state)
}


static PyTypeObject _PyExc_MemoryError = {
PyTypeObject _PyExc_MemoryError = {
PyVarObject_HEAD_INIT(NULL, 0)
"MemoryError",
sizeof(PyBaseExceptionObject),
Expand All @@ -3339,9 +3337,6 @@ static PyTypeObject _PyExc_MemoryError = {
};
PyObject *PyExc_MemoryError = (PyObject *) &_PyExc_MemoryError;

static PyBaseExceptionObject last_resort_memory_error = {
_PyObject_IMMORTAL_INIT(&_PyExc_MemoryError)
};

/*
* BufferError extends Exception
Expand Down
4 changes: 2 additions & 2 deletions Python/intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ list_to_tuple(PyThreadState* unused, PyObject *v)
return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));
}

instrinsic_func1
const instrinsic_func1
_PyIntrinsics_UnaryFunctions[] = {
[0] = no_intrinsic,
[INTRINSIC_PRINT] = print_expr,
Expand All @@ -221,7 +221,7 @@ prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs)
return _PyExc_PrepReraiseStar(orig, excs);
}

instrinsic_func2
const instrinsic_func2
_PyIntrinsics_BinaryFunctions[] = {
[INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star,
};
Expand Down
22 changes: 17 additions & 5 deletions Tools/c-analyzer/c_parser/parser/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@
)


def log_match(group, m):
def log_match(group, m, depth_before=None, depth_after=None):
from . import _logger
text = m.group(0)
if text.startswith(('(', ')')) or text.endswith(('(', ')')):
_logger.debug(f'matched <{group}> ({text!r})')

if m is not None:
text = m.group(0)
if text.startswith(('(', ')')) or text.endswith(('(', ')')):
_logger.debug(f'matched <{group}> ({text!r})')
else:
_logger.debug(f'matched <{group}> ({text})')

elif depth_before is not None or depth_after is not None:
if depth_before is None:
depth_before = '???'
elif depth_after is None:
depth_after = '???'
_logger.log(1, f'depth: %s -> %s', depth_before, depth_after)

else:
_logger.debug(f'matched <{group}> ({text})')
raise NotImplementedError('this should not have been hit')


#############################
Expand Down
25 changes: 14 additions & 11 deletions Tools/c-analyzer/c_parser/parser/_func_body.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ def parse_function_body(name, text, resolve, source, anon_name, parent):
) = m.groups()

if empty:
log_match('', m)
log_match('', m, depth)
resolve(None, None, None, text)
yield None, text
elif inline_kind:
log_match('', m)
log_match('', m, depth)
kind = inline_kind
name = inline_name or anon_name('inline-')
data = [] # members
Expand All @@ -92,7 +92,7 @@ def parse_function_body(name, text, resolve, source, anon_name, parent):
# XXX Should "parent" really be None for inline type decls?
yield resolve(kind, data, name, text, None), text
elif block_close:
log_match('', m)
log_match('', m, depth)
depth -= 1
resolve(None, None, None, text)
# XXX This isn't great. Calling resolve() should have
Expand All @@ -101,13 +101,13 @@ def parse_function_body(name, text, resolve, source, anon_name, parent):
# needs to be fixed.
yield None, text
elif compound_bare:
log_match('', m)
log_match('', m, depth)
yield resolve('statement', compound_bare, None, text, parent), text
elif compound_labeled:
log_match('', m)
log_match('', m, depth)
yield resolve('statement', compound_labeled, None, text, parent), text
elif compound_paren:
log_match('', m)
log_match('', m, depth)
try:
pos = match_paren(text)
except ValueError:
Expand All @@ -132,7 +132,7 @@ def parse_function_body(name, text, resolve, source, anon_name, parent):
}
yield resolve('statement', data, None, text, parent), text
elif block_open:
log_match('', m)
log_match('', m, depth)
depth += 1
if block_leading:
# An inline block: the last evaluated expression is used
Expand All @@ -144,10 +144,10 @@ def parse_function_body(name, text, resolve, source, anon_name, parent):
resolve(None, None, None, text)
yield None, text
elif simple_ending:
log_match('', m)
log_match('', m, depth)
yield resolve('statement', simple_stmt, None, text, parent), text
elif var_ending:
log_match('', m)
log_match('', m, depth)
kind = 'variable'
_, name, vartype = parse_var_decl(decl)
data = {
Expand Down Expand Up @@ -220,7 +220,7 @@ def _parse_next_local_static(m, srcinfo, anon_name, func, depth):
remainder = srcinfo.text[m.end():]

if inline_kind:
log_match('func inline', m)
log_match('func inline', m, depth, depth)
kind = inline_kind
name = inline_name or anon_name('inline-')
# Immediately emit a forward declaration.
Expand Down Expand Up @@ -249,7 +249,7 @@ def parse_body(source):
yield parse_body, depth

elif static_decl:
log_match('local variable', m)
log_match('local variable', m, depth, depth)
_, name, data = parse_var_decl(static_decl)

yield srcinfo.resolve('variable', data, name, parent=func), depth
Expand All @@ -266,10 +266,13 @@ def parse_body(source):
else:
log_match('func other', m)
if block_open:
log_match('func other', None, depth, depth + 1)
depth += 1
elif block_close:
log_match('func other', None, depth, depth - 1)
depth -= 1
elif stmt_end:
log_match('func other', None, depth, depth)
pass
else:
# This should be unreachable.
Expand Down
3 changes: 2 additions & 1 deletion Tools/c-analyzer/c_parser/preprocessor/gcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
[^()]*
)*
) # <args>
( [)] [)] )? # <closed>
( [)] [)] ) # <closed>
''', re.VERBOSE)

POST_ARGS = (
Expand Down Expand Up @@ -156,6 +156,7 @@ def _iter_top_include_lines(lines, topfile, cwd,
if name != 'pragma':
raise Exception(line)
else:
line = re.sub(r'__inline__', 'inline', line)
if not raw:
line, partial = _strip_directives(line, partial=partial)
yield _common.SourceLine(
Expand Down
9 changes: 8 additions & 1 deletion Tools/c-analyzer/cpython/_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,14 @@ def clean_lines(text):
* ./Include
* ./Include/internal

Modules/_decimal/**/*.c Modules/_decimal/libmpdec
Modules/_hacl/*.c Modules/_hacl/include
Modules/_hacl/*.h Modules/_hacl/include
Modules/_tkinter.c /usr/include/tcl8.6
Modules/md5module.c Modules/_hacl/include
Modules/sha1module.c Modules/_hacl/include
Modules/sha2module.c Modules/_hacl/include
Modules/tkappinit.c /usr/include/tcl
Modules/_decimal/**/*.c Modules/_decimal/libmpdec
Objects/stringlib/*.h Objects

# @end=tsv@
Expand Down Expand Up @@ -173,6 +178,7 @@ def clean_lines(text):
Modules/_functoolsmodule.c Py_BUILD_CORE 1
Modules/_heapqmodule.c Py_BUILD_CORE 1
Modules/_io/*.c Py_BUILD_CORE 1
Modules/_io/*.h Py_BUILD_CORE 1
Modules/_localemodule.c Py_BUILD_CORE 1
Modules/_operator.c Py_BUILD_CORE 1
Modules/_posixsubprocess.c Py_BUILD_CORE 1
Expand Down Expand Up @@ -296,6 +302,7 @@ def clean_lines(text):
# First match wins.
_abs('Modules/_ctypes/ctypes.h'): (5_000, 500),
_abs('Modules/_datetimemodule.c'): (20_000, 300),
_abs('Modules/_hacl/*.c'): (200_000, 500),
_abs('Modules/posixmodule.c'): (20_000, 500),
_abs('Modules/termios.c'): (10_000, 800),
_abs('Modules/_testcapimodule.c'): (20_000, 400),
Expand Down
2 changes: 1 addition & 1 deletion Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ Modules/_tkinter.c - command_mutex -
Modules/_tkinter.c - HeadFHCD -
Modules/_tkinter.c - stdin_ready -
Modules/_tkinter.c - event_tstate -
Modules/_xxsubinterpretersmodule.c - _globals -
Modules/_xxinterpchannelsmodule.c - _globals -
Modules/readline.c - completer_word_break_characters -
Modules/readline.c - _history_length -
Modules/readline.c - should_auto_add_history -
Expand Down
30 changes: 28 additions & 2 deletions Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ Modules/_decimal/_decimal.c - invalid_signals_err -
Modules/_decimal/_decimal.c - signal_map -
Modules/_decimal/_decimal.c - ssize_constants -
Modules/_elementtree.c - ExpatMemoryHandler -
Modules/_hashopenssl.c - py_hashes -
Modules/_hacl/Hacl_Hash_SHA1.c - _h0 -
Modules/_hacl/Hacl_Hash_MD5.c - _h0 -
Modules/_hacl/Hacl_Hash_MD5.c - _t -
Modules/_io/_iomodule.c - static_types -
Modules/_io/textio.c - encodefuncs -
Modules/_io/winconsoleio.c - _PyWindowsConsoleIO_Type -
Expand All @@ -218,9 +222,10 @@ Modules/_sre/sre_targets.h - sre_targets -
Modules/_sre.c pattern_repr flag_names -
Modules/_struct.c - bigendian_table -
Modules/_struct.c - lilendian_table -
Modules/_struct.c - native_table -
Modules/_tkinter.c - state_key -
Modules/_xxsubinterpretersmodule.c - _channelid_end_recv -
Modules/_xxsubinterpretersmodule.c - _channelid_end_send -
Modules/_xxinterpchannelsmodule.c - _channelid_end_recv -
Modules/_xxinterpchannelsmodule.c - _channelid_end_send -
Modules/_zoneinfo.c - DAYS_BEFORE_MONTH -
Modules/_zoneinfo.c - DAYS_IN_MONTH -
Modules/arraymodule.c - descriptors -
Expand Down Expand Up @@ -332,12 +337,15 @@ Python/frozen.c - _PyImport_FrozenTest -
Python/getopt.c - longopts -
Python/import.c - _PyImport_Inittab -
Python/import.c - _PySys_ImplCacheTag -
Python/intrinsics.c - _PyIntrinsics_UnaryFunctions -
Python/intrinsics.c - _PyIntrinsics_BinaryFunctions -
Python/opcode_targets.h - opcode_targets -
Python/perf_trampoline.c - _Py_perfmap_callbacks -
Python/pyhash.c - PyHash_Func -
Python/pylifecycle.c - _C_LOCALE_WARNING -
Python/pylifecycle.c - _PyOS_mystrnicmp_hack -
Python/pylifecycle.c - _TARGET_LOCALES -
Python/pylifecycle.c - INTERPRETER_TRAMPOLINE_CODEDEF -
Python/pystate.c - initial -
Python/specialize.c - adaptive_opcodes -
Python/specialize.c - cache_requirements -
Expand Down Expand Up @@ -392,8 +400,23 @@ Modules/_testbuffer.c ndarray_memoryview_from_buffer strides -
Modules/_testbuffer.c ndarray_memoryview_from_buffer suboffsets -
Modules/_testbuffer.c ndarray_push kwlist -
Modules/_testbuffer.c staticarray_init kwlist -
Modules/_testcapi/code.c get_code_extra_index key -
Modules/_testcapi/datetime.c - test_run_counter -
Modules/_testcapi/exceptions.c - PyRecursingInfinitelyError_Type -
Modules/_testcapi/heaptype.c - _testcapimodule -
Modules/_testcapi/mem.c - FmData -
Modules/_testcapi/mem.c - FmHook -
Modules/_testcapi/structmember.c - test_structmembersType_OldAPI -
Modules/_testcapi/unicode.c - _testcapimodule -
Modules/_testcapi/watchers.c - g_dict_watch_events -
Modules/_testcapi/watchers.c - g_dict_watchers_installed -
Modules/_testcapi/watchers.c - g_type_modified_events -
Modules/_testcapi/watchers.c - g_type_watchers_installed -
Modules/_testcapi/watchers.c - num_code_object_created_events -
Modules/_testcapi/watchers.c - num_code_object_destroyed_events -
Modules/_testcapi/watchers.c - pyfunc_watchers -
Modules/_testcapi/watchers.c - func_watcher_ids -
Modules/_testcapi/watchers.c - func_watcher_callbacks -
Modules/_testcapimodule.c - ContainerNoGC_members -
Modules/_testcapimodule.c - ContainerNoGC_type -
Modules/_testcapimodule.c - FmData -
Expand Down Expand Up @@ -460,11 +483,13 @@ Modules/_testcapimodule.c - meth_static_methods -
Modules/_testcapimodule.c - ml -
Modules/_testcapimodule.c - str1 -
Modules/_testcapimodule.c - str2 -
Modules/_testcapimodule.c - test_c_thread -
Modules/_testcapimodule.c - test_members -
Modules/_testcapimodule.c - test_run_counter -
Modules/_testcapimodule.c - test_structmembersType -
Modules/_testcapimodule.c - thread_done -
Modules/_testcapimodule.c - x -
Modules/_testcapimodule.c - wait_done -
Modules/_testcapimodule.c getargs_keyword_only keywords -
Modules/_testcapimodule.c getargs_keywords keywords -
Modules/_testcapimodule.c getargs_positional_only_and_keywords keywords -
Expand Down Expand Up @@ -526,6 +551,7 @@ Modules/_testmultiphase.c - slots_exec_unreported_exception -
Modules/_testmultiphase.c - slots_nonmodule_with_exec_slots -
Modules/_testmultiphase.c - testexport_methods -
Modules/_testmultiphase.c - uninitialized_def -
Modules/_testsinglephase.c - global_state -
Modules/_xxtestfuzz/_xxtestfuzz.c - _fuzzmodule -
Modules/_xxtestfuzz/_xxtestfuzz.c - module_methods -
Modules/_xxtestfuzz/fuzzer.c - SRE_FLAG_DEBUG -
Expand Down