mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Python: CG trace: Handle list-comprehension and iteration
Which relies on LOAD_CONST and MAKE_FUNCTION
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
for i in range(10):
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
[i + 1 for i in range(10)]
|
||||||
|
l = list(range(10))
|
||||||
|
[i + 1 for i in l]
|
||||||
|
[i + 1 for i in l]
|
||||||
@@ -3,7 +3,7 @@ import dis
|
|||||||
import logging
|
import logging
|
||||||
from dis import Instruction
|
from dis import Instruction
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
from typing import List
|
from typing import Any, List
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -18,6 +18,16 @@ class BytecodeExpr:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True, eq=True, order=True)
|
||||||
|
class BytecodeConst(BytecodeExpr):
|
||||||
|
"""FOR LOAD_CONST"""
|
||||||
|
|
||||||
|
value: Any
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True, eq=True, order=True)
|
@dataclasses.dataclass(frozen=True, eq=True, order=True)
|
||||||
class BytecodeVariableName(BytecodeExpr):
|
class BytecodeVariableName(BytecodeExpr):
|
||||||
name: str
|
name: str
|
||||||
@@ -51,6 +61,16 @@ class BytecodeUnknown(BytecodeExpr):
|
|||||||
return f"<{self.opname}>"
|
return f"<{self.opname}>"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True, eq=True, order=True)
|
||||||
|
class BytecodeMakeFunction(BytecodeExpr):
|
||||||
|
"""For MAKE_FUNCTION opcode"""
|
||||||
|
|
||||||
|
qualified_name: BytecodeExpr
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"<MAKE_FUNCTION>(qualified_name={self.qualified_name})>"
|
||||||
|
|
||||||
|
|
||||||
def expr_that_added_elem_to_stack(
|
def expr_that_added_elem_to_stack(
|
||||||
instructions: List[Instruction], start_index: int, stack_pos: int
|
instructions: List[Instruction], start_index: int, stack_pos: int
|
||||||
):
|
):
|
||||||
@@ -101,6 +121,9 @@ def expr_from_instruction(instructions: List[Instruction], index: int) -> Byteco
|
|||||||
if inst.opname in ["LOAD_GLOBAL", "LOAD_FAST", "LOAD_NAME"]:
|
if inst.opname in ["LOAD_GLOBAL", "LOAD_FAST", "LOAD_NAME"]:
|
||||||
return BytecodeVariableName(inst.argval)
|
return BytecodeVariableName(inst.argval)
|
||||||
|
|
||||||
|
elif inst.opname in ["LOAD_CONST"]:
|
||||||
|
return BytecodeConst(inst.argval)
|
||||||
|
|
||||||
# https://docs.python.org/3/library/dis.html#opcode-LOAD_METHOD
|
# https://docs.python.org/3/library/dis.html#opcode-LOAD_METHOD
|
||||||
# https://docs.python.org/3/library/dis.html#opcode-LOAD_ATTR
|
# https://docs.python.org/3/library/dis.html#opcode-LOAD_ATTR
|
||||||
elif inst.opname in ["LOAD_METHOD", "LOAD_ATTR"]:
|
elif inst.opname in ["LOAD_METHOD", "LOAD_ATTR"]:
|
||||||
@@ -122,11 +145,16 @@ def expr_from_instruction(instructions: List[Instruction], index: int) -> Byteco
|
|||||||
)
|
)
|
||||||
return BytecodeCall(function=func_expr)
|
return BytecodeCall(function=func_expr)
|
||||||
|
|
||||||
else:
|
elif inst.opname in ["MAKE_FUNCTION"]:
|
||||||
# LOAD_BUILD_CLASS is included here intentionally for now, since I don't really
|
name_expr = expr_that_added_elem_to_stack(instructions, index - 1, 0)
|
||||||
# know what to do about it.
|
assert isinstance(name_expr, BytecodeConst)
|
||||||
|
return BytecodeMakeFunction(qualified_name=name_expr)
|
||||||
|
|
||||||
|
# LOAD_BUILD_CLASS is included here intentionally for now, since I don't really
|
||||||
|
# know what to do about it.
|
||||||
|
if inst.opname not in ["LOAD_BUILD_CLASS"]:
|
||||||
LOGGER.warning(f"Don't know how to handle this type of instruction: {inst}")
|
LOGGER.warning(f"Don't know how to handle this type of instruction: {inst}")
|
||||||
return BytecodeUnknown(inst.opname)
|
return BytecodeUnknown(inst.opname)
|
||||||
|
|
||||||
|
|
||||||
def expr_from_frame(frame: FrameType) -> BytecodeExpr:
|
def expr_from_frame(frame: FrameType) -> BytecodeExpr:
|
||||||
|
|||||||
Reference in New Issue
Block a user