diff options
author | Mark Shannon <mark@hotpy.org> | 2021-04-29 12:12:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-29 12:12:51 (GMT) |
commit | c76da79b37d2bcbe575cc927ba0a9b7a9ce465db (patch) | |
tree | cf5e884131b3f44f038355ff4980cfbb97a6e228 /Objects | |
parent | 53dd6c99b39d90935c00bc1558582e494641248e (diff) | |
download | cpython-c76da79b37d2bcbe575cc927ba0a9b7a9ce465db.zip cpython-c76da79b37d2bcbe575cc927ba0a9b7a9ce465db.tar.gz cpython-c76da79b37d2bcbe575cc927ba0a9b7a9ce465db.tar.bz2 |
bpo-42739: Don't use sentinels to mark end of line table. (GH-25657)
* Add length parameter to PyLineTable_InitAddressRange and doen't use sentinel values at end of table. Makes the line number table more robust.
* Update PyCodeAddressRange to match PEP 626.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/codeobject.c | 41 | ||||
-rw-r--r-- | Objects/lnotab_notes.txt | 4 |
2 files changed, 21 insertions, 24 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 9bb49f1..c76ac90 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -456,15 +456,15 @@ code_getlnotab(PyCodeObject *code, void *closure) } _PyCode_InitAddressRange(code, &bounds); while (PyLineTable_NextAddressRange(&bounds)) { - if (bounds.ar_computed_line != line) { + if (bounds.opaque.computed_line != line) { int bdelta = bounds.ar_start - code_offset; - int ldelta = bounds.ar_computed_line - line; + int ldelta = bounds.opaque.computed_line - line; if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) { Py_DECREF(bytes); return NULL; } code_offset = bounds.ar_start; - line = bounds.ar_computed_line; + line = bounds.opaque.computed_line; } } _PyBytes_Resize(&bytes, table_offset); @@ -1120,20 +1120,20 @@ code_linesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args)) static void retreat(PyCodeAddressRange *bounds) { - int ldelta = ((signed char *)bounds->lo_next)[-1]; + int ldelta = ((signed char *)bounds->opaque.lo_next)[-1]; if (ldelta == -128) { ldelta = 0; } - bounds->ar_computed_line -= ldelta; - bounds->lo_next -= 2; + bounds->opaque.computed_line -= ldelta; + bounds->opaque.lo_next -= 2; bounds->ar_end = bounds->ar_start; - bounds->ar_start -= ((unsigned char *)bounds->lo_next)[-2]; - ldelta = ((signed char *)bounds->lo_next)[-1]; + bounds->ar_start -= ((unsigned char *)bounds->opaque.lo_next)[-2]; + ldelta = ((signed char *)bounds->opaque.lo_next)[-1]; if (ldelta == -128) { bounds->ar_line = -1; } else { - bounds->ar_line = bounds->ar_computed_line; + bounds->ar_line = bounds->opaque.computed_line; } } @@ -1141,23 +1141,22 @@ static void advance(PyCodeAddressRange *bounds) { bounds->ar_start = bounds->ar_end; - int delta = ((unsigned char *)bounds->lo_next)[0]; - assert (delta < 255); + int delta = ((unsigned char *)bounds->opaque.lo_next)[0]; bounds->ar_end += delta; - int ldelta = ((signed char *)bounds->lo_next)[1]; - bounds->lo_next += 2; + int ldelta = ((signed char *)bounds->opaque.lo_next)[1]; + bounds->opaque.lo_next += 2; if (ldelta == -128) { bounds->ar_line = -1; } else { - bounds->ar_computed_line += ldelta; - bounds->ar_line = bounds->ar_computed_line; + bounds->opaque.computed_line += ldelta; + bounds->ar_line = bounds->opaque.computed_line; } } static inline int at_end(PyCodeAddressRange *bounds) { - return ((unsigned char *)bounds->lo_next)[0] == 255; + return bounds->opaque.lo_next >= bounds->opaque.limit; } int @@ -1256,12 +1255,13 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq) } void -PyLineTable_InitAddressRange(char *linetable, int firstlineno, PyCodeAddressRange *range) +PyLineTable_InitAddressRange(char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range) { - range->lo_next = linetable; + range->opaque.lo_next = linetable; + range->opaque.limit = range->opaque.lo_next + length; range->ar_start = -1; range->ar_end = 0; - range->ar_computed_line = firstlineno; + range->opaque.computed_line = firstlineno; range->ar_line = -1; } @@ -1269,7 +1269,8 @@ int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds) { char *linetable = PyBytes_AS_STRING(co->co_linetable); - PyLineTable_InitAddressRange(linetable, co->co_firstlineno, bounds); + Py_ssize_t length = PyBytes_GET_SIZE(co->co_linetable); + PyLineTable_InitAddressRange(linetable, length, co->co_firstlineno, bounds); return bounds->ar_line; } diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt index 59c6525..f482310 100644 --- a/Objects/lnotab_notes.txt +++ b/Objects/lnotab_notes.txt @@ -39,7 +39,6 @@ Note that the end - start value is always positive. Finally, in order to fit into a single byte we need to convert start deltas to the range 0 <= delta <= 254, and line deltas to the range -127 <= delta <= 127. A line delta of -128 is used to indicate no line number. -A start delta of 255 is used as a sentinel to mark the end of the table. Also note that a delta of zero indicates that there are no bytecodes in the given range, which means we can use an invalid line number for that range. @@ -54,7 +53,6 @@ Final form: 16 +1 0 +127 (line 135, but the range is empty as no bytecodes are at line 135) 4 +73 - 255 (end mark) --- Iterating over the table. ------------------------- @@ -68,8 +66,6 @@ def co_lines(code): end = 0 table_iter = iter(code.internal_line_table): for sdelta, ldelta in table_iter: - if sdelta == 255: - break if ldelta == 0: # No change to line number, just accumulate changes to end end += odelta continue |