Two crash cases involving collections.namedtuple
Description
We found two crash cases involving collections.namedtuple. The first (heap-buffer-overvflow at mp_seq_multiply) and second cases (null-dereference at mp_obj_equal_not_equal) both attempted to operate on a namedtuple object indirectly.
All PoCs were not straightforward to analyze as-is, so we compared the behaviors to the reference implementation (CPython). In the first case, CPython threw an exception while creating a namedtuple object (v4 in the PoC). In the second case, the exception happened while deriving a superclass of builtins (v6 in the PoC) using an already-created namedtuple object.
We've attached two PoCs for each cases.
Proof of Concept
$ # build unix port with ASAN, at the root source code directory.
$ export CC=clang
$ export CXX=clang++
$ export CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
$ export CXXFLAGS=$CFLAGS
$ export LDFLAGS=$CFLAGS
$ export DEBUG=1
$ make -C mpy-cross -j
$ make -C ports/unix -j all lib
$
$ # run a poc.
$ export ASAN_OPTIONS="detect_leaks=0"
$ ./ports/unix/build-standard/micropython <poc_file>
Environment
Ubuntu 20.04
Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz
Memory: 64 GB
Affected Version
v1.20.0 (commit a3862e726, latest as of 2023-09-26)
v1.20.0 (commit 813d559bc, 2023-06-19)
Discovered in the UNIX port version.
namedtuple crash with empty field list
On the Unix port:
>>> from collections import namedtuple
>>> n = namedtuple('a', '')
>>> n()
Segmentation fault (core dumped)
The crash comes from namedtuple_make_new which tries to set tuple->base.type = type_in;, but tuple is mp_const_empty_tuple.
The crash didn't happen on PYBD, however it appears to be overwriting the type of mp_const_empty_tuple.
Additionally, MicroPython allows a namedtuple with an empty name, e.g.
>>> namedtuple('', 'a')
<class ''>
whereas CPython:
>>> namedtuple('', 'a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/collections/__init__.py", line 358, in namedtuple
raise ValueError('Type names and field names must be valid '
ValueError: Type names and field names must be valid identifiers: ''