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.
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;
 }