From 5a6ea35d857fd6232838a12c69211dce2bcf3e5a Mon Sep 17 00:00:00 2001
From: Julian Gilbey <jdg@debian.org>
Date: Fri, 13 Oct 2023 12:07:05 +0100
Subject: [PATCH] New upstream version 0.15.1

---
 .github/workflows/cis.yml        |  4 ++--
 .github/workflows/docs.yml       |  2 +-
 .github/workflows/frameworks.yml |  2 +-
 .github/workflows/release.yml    |  4 ++--
 doc/api.rst                      | 12 ++++++------
 doc/changelog.rst                | 12 +++++++++++-
 src/bytecode/concrete.py         |  3 ++-
 src/bytecode/instr.py            | 18 +++++++++++++-----
 tests/test_concrete.py           |  6 +++++-
 tests/test_instr.py              |  8 +++++++-
 10 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/cis.yml b/.github/workflows/cis.yml
index 09e2da8..f1e1922 100644
--- a/.github/workflows/cis.yml
+++ b/.github/workflows/cis.yml
@@ -21,7 +21,7 @@ jobs:
     name: Lint code
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up Python
         uses: actions/setup-python@v4
         with:
@@ -54,7 +54,7 @@ jobs:
           - python-version: "3.12-dev"
             toxenv: py312
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index cff1aa9..a8ab0f3 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -20,7 +20,7 @@ jobs:
     name: Docs building
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
diff --git a/.github/workflows/frameworks.yml b/.github/workflows/frameworks.yml
index b6e4a39..79b4be8 100644
--- a/.github/workflows/frameworks.yml
+++ b/.github/workflows/frameworks.yml
@@ -25,7 +25,7 @@ jobs:
         python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
 
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f25f83a..aa44198 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,7 +13,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
@@ -43,7 +43,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: Get history and tags for SCM versioning to work
         run: |
           git fetch --prune --unshallow
diff --git a/doc/api.rst b/doc/api.rst
index cf91ba8..db54cae 100644
--- a/doc/api.rst
+++ b/doc/api.rst
@@ -351,11 +351,11 @@ Intrinsic operations
 
 .. class:: Intrinsic1Op
 
-   Enum for the argument of the ``CALL_INSTRINSIC_1`` instruction (3.12+).
+   Enum for the argument of the ``CALL_INTRINSIC_1`` instruction (3.12+).
 
-   ``INSTRINSIC_1_INVALID``
-   ``INSTRINSIC_PRINT``
-   ``INSTRINSIC_IMPORT_STAR``
+   ``INTRINSIC_1_INVALID``
+   ``INTRINSIC_PRINT``
+   ``INTRINSIC_IMPORT_STAR``
    ``INTRINSIC_STOPITERATION_ERROR``
    ``INTRINSIC_ASYNC_GEN_WRAP``
    ``INTRINSIC_UNARY_POSITIVE``
@@ -368,9 +368,9 @@ Intrinsic operations
 
 .. class:: Intrinsic2Op
 
-   Enum for the argument of the ``CALL_INSTRINSIC_2`` instruction (3.12+).
+   Enum for the argument of the ``CALL_INTRINSIC_2`` instruction (3.12+).
 
-   ``INSTRINSIC_2_INVALID``
+   ``INTRINSIC_2_INVALID``
    ``INTRINSIC_PREP_RERAISE_STAR``
    ``INTRINSIC_TYPEVAR_WITH_BOUND``
    ``INTRINSIC_TYPEVAR_WITH_CONSTRAINTS``
diff --git a/doc/changelog.rst b/doc/changelog.rst
index 01a1950..dfc4328 100644
--- a/doc/changelog.rst
+++ b/doc/changelog.rst
@@ -1,6 +1,16 @@
 ChangeLog
 =========
 
+2023-10-13: Version 0.15.1
+--------------------------
+
+Bugfixes:
+
+- Disallow creating an instruction targeting a pseudo/instrumented opcode PR #133
+- Fixes encoding of 0 as a varint PR #132
+- Correct spelling of "INTRINSIC" in several places; this affected
+  some ops in Python 3.12.  PR #131
+
 2023-09-01: Version 0.15.0
 --------------------------
 
@@ -17,7 +27,7 @@ New features:
     a ``tuple[bool, bool, str]`` as argument
   - ``POP_JUMP_IF_*`` instructions are undirected in Python 3.12
   - ``YIELD_VALUE`` now takes an argument
-  - Support for ``CALL_INSTRINSIC_1/2`` led to the addition of 2 new enums to
+  - Support for ``CALL_INTRINSIC_1/2`` led to the addition of 2 new enums to
     represent the argument
 
 2023-05-24: Version 0.14.2
diff --git a/src/bytecode/concrete.py b/src/bytecode/concrete.py
index 4a65a5e..4908e1c 100644
--- a/src/bytecode/concrete.py
+++ b/src/bytecode/concrete.py
@@ -818,9 +818,10 @@ class ConcreteBytecode(_bytecode._BaseBytecodeList[Union[ConcreteInstr, SetLinen
         while value:
             temp.append(value & 63 | (64 if temp else 0))
             value >>= 6
+        temp = temp or [0]
         if set_begin_marker:
             temp[-1] |= 128
-        return reversed(temp or [0])
+        return reversed(temp)
 
     def _assemble_exception_table(self) -> bytes:
         table = bytearray()
diff --git a/src/bytecode/instr.py b/src/bytecode/instr.py
index f65e5af..e927cdf 100644
--- a/src/bytecode/instr.py
+++ b/src/bytecode/instr.py
@@ -14,7 +14,9 @@ except ImportError:
 
 import bytecode as _bytecode
 
-# --- Instruction argument tools and abstractions
+# --- Instruction argument tools and
+
+MIN_INSTRUMENTED_OPCODE = getattr(_opcode, "MIN_INSTRUMENTED_OPCODE", 256)
 
 # Instructions relying on a bit to modify its behavior.
 # The lowest bit is used to encode custom behavior.
@@ -104,9 +106,9 @@ class BinaryOp(enum.IntEnum):
 
 @enum.unique
 class Intrinsic1Op(enum.IntEnum):
-    INSTRINSIC_1_INVALID = 0
-    INSTRINSIC_PRINT = 1
-    INSTRINSIC_IMPORT_STAR = 2
+    INTRINSIC_1_INVALID = 0
+    INTRINSIC_PRINT = 1
+    INTRINSIC_IMPORT_STAR = 2
     INTRINSIC_STOPITERATION_ERROR = 3
     INTRINSIC_ASYNC_GEN_WRAP = 4
     INTRINSIC_UNARY_POSITIVE = 5
@@ -120,7 +122,7 @@ class Intrinsic1Op(enum.IntEnum):
 
 @enum.unique
 class Intrinsic2Op(enum.IntEnum):
-    INSTRINSIC_2_INVALID = 0
+    INTRINSIC_2_INVALID = 0
     INTRINSIC_PREP_RERAISE_STAR = 1
     INTRINSIC_TYPEVAR_WITH_BOUND = 2
     INTRINSIC_TYPEVAR_WITH_CONSTRAINTS = 3
@@ -734,6 +736,12 @@ class BaseInstr(Generic[A]):
         except KeyError:
             raise ValueError(f"invalid operation name: {name}")
 
+        if opcode >= MIN_INSTRUMENTED_OPCODE:
+            raise ValueError(
+                f"operation {name} is an instrumented or pseudo opcode. "
+                "Only base opcodes are supported"
+            )
+
         self._check_arg(name, opcode, arg)
 
         self._name = name
diff --git a/tests/test_concrete.py b/tests/test_concrete.py
index 32c179a..3b75ba9 100644
--- a/tests/test_concrete.py
+++ b/tests/test_concrete.py
@@ -529,7 +529,6 @@ class ConcreteBytecodeTests(TestCase):
             ],
         )
 
-    # XXX adjust test for 3.12 in which load_classderef does not exist anymore
     def test_load_classderef(self):
         i_name = (
             "LOAD_FROM_DICT_OR_DEREF"
@@ -682,6 +681,11 @@ class ConcreteBytecodeTests(TestCase):
         )
         self.assertInstructionListEqual(concrete, concrete.copy())
 
+    def test_encode_varint(self):
+        self.assertListEqual(list(ConcreteBytecode._encode_varint(0)), [0])
+        self.assertListEqual(list(ConcreteBytecode._encode_varint(0, True)), [128])
+        self.assertListEqual(list(ConcreteBytecode._encode_varint(64, False)), [65, 0])
+
 
 class ConcreteFromCodeTests(TestCase):
     def test_extended_arg(self):
diff --git a/tests/test_instr.py b/tests/test_instr.py
index d36c315..1437b87 100644
--- a/tests/test_instr.py
+++ b/tests/test_instr.py
@@ -138,6 +138,12 @@ class InstrTests(TestCase):
         self.assertIn("arg", r)
         self.assertIn("_x_", r)
 
+    def test_reject_pseudo_opcode(self):
+        if sys.version_info >= (3, 12):
+            with self.assertRaises(ValueError) as e:
+                Instr("LOAD_METHOD", "x")
+            self.assertIn("is an instrumented or pseudo opcode", str(e.exception))
+
     def test_invalid_arg(self):
         label = Label()
         block = BasicBlock()
@@ -208,7 +214,7 @@ class InstrTests(TestCase):
 
         for name in [opcode.opname[i] for i in INTRINSIC_1OP]:
             self.assertRaises(TypeError, Instr, name, 1)
-            Instr(name, Intrinsic1Op.INSTRINSIC_PRINT)
+            Instr(name, Intrinsic1Op.INTRINSIC_PRINT)
 
         for name in [opcode.opname[i] for i in INTRINSIC_2OP]:
             self.assertRaises(TypeError, Instr, name, 1)
-- 
GitLab