Skip to content

Commit f0c34f1

Browse files
Fix TSA #2816216: suppress Flawfinder false positive on Cython DIGIT_PAIRS_8 memcpy (#2028)
* Fix TSA #2816216: suppress Flawfinder false positive on Cython DIGIT_PAIRS_8 memcpy Flawfinder's buffer/memcpy rule (CWE-120) fires on any memcpy() call by default. The flagged call sits inside the Cython 3.x integer formatter __Pyx____Pyx_PyUnicode_From_int (case 'o'): memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2); It is provably safe: * dpos points into the stack buffer `digits[sizeof(int)*3+2]` (14 bytes for a 32-bit int); `dpos -= 2` immediately precedes the copy and the enclosing do/while loop iterates at most ceil(log_64(max_int)) times, so dpos always stays >= digits. * DIGIT_PAIRS_8 is a 128-byte compile-time constant table containing the 64 two-character octal digit pairs "00".."77". `digit_pos = abs(remaining % 64)`, so `digit_pos * 2` ranges over [0, 126] and reads 2 bytes from offset [0, 127] -- within the table. * The size argument is the compile-time constant 2. Add an inline /* Flawfinder: ignore */ annotation on the flagged line in the Cython-generated pydevd_cython.c and extend the existing post-processing block in setup_pydevd_cython.py so the annotation is re-applied automatically whenever Cython regenerates the .c files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix SyntaxError: add missing closing paren on DIGIT_PAIRS_8 .replace() call Same merge-from-main artifact as #2029: the closing ')' of the new DIGIT_PAIRS_8 '.replace(...)' call was dropped when the 'read<end' '.replace(...)' block was spliced in, leaving the second call's args being parsed as continued positional args to the first. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4c70e13 commit f0c34f1

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

src/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_cython.c

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/debugpy/_vendored/pydevd/setup_pydevd_cython.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,16 @@ def build_extension(dir_name, extension_name, target_pydevd_name, force_cython,
177177
c_file_contents = c_file_contents.replace(r"_pydevd_bundle\\pydevd_cython.pxd", "_pydevd_bundle/pydevd_cython.pxd")
178178
c_file_contents = c_file_contents.replace(r"_pydevd_bundle\\pydevd_cython.pyx", "_pydevd_bundle/pydevd_cython.pyx")
179179

180+
# Suppress Flawfinder false positive (CWE-120) in the Cython 3.x
181+
# CIntToPyUnicode boilerplate (`__Pyx____Pyx_PyUnicode_From_int`): the destination
182+
# `dpos` is a stack buffer of size `sizeof(int)*3+2`, and `dpos -= 2` immediately
183+
# precedes a 2-byte memcpy from the 128-byte constant table `DIGIT_PAIRS_8`
184+
# indexed by `digit_pos * 2` where `digit_pos = abs(remaining % 64)`.
185+
c_file_contents = c_file_contents.replace(
186+
" memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2);\n",
187+
" memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2); /* Flawfinder: ignore */\n",
188+
)
189+
180190
# Suppress Flawfinder false positive (CWE-120/CWE-20) in the
181191
# Cython 3.x ModuleStateLookup boilerplate (`__Pyx_State_ConvertFromInterpIdAsIndex`):
182192
# `read` is a bounded pointer iterator (not POSIX read()), and the loop is

0 commit comments

Comments
 (0)