# HG changeset patch # User Paul Boddie # Date 1531150355 -7200 # Node ID 9adc6e8a6fed51a7707e4b5e63da977811ca2a5c # Parent ea1e1157afc4bea57e7ce3305e837746db651d54 Introduced restrictions on privileged attributes, allowing internal access only. diff -r ea1e1157afc4 -r 9adc6e8a6fed common.py --- a/common.py Thu Jul 05 23:41:16 2018 +0200 +++ b/common.py Mon Jul 09 17:32:35 2018 +0200 @@ -462,7 +462,9 @@ for i, node in enumerate(n.nodes): statements.append( compiler.ast.Assign([node], compiler.ast.CallFunc( - compiler.ast.Getattr(compiler.ast.Name(temp), "__get_single_item_unchecked__"), + compiler.ast.Getattr(compiler.ast.Name(temp), + "__get_single_item_unchecked__", + privileged=True), [compiler.ast.Const(i, str(i))])) ) @@ -1591,6 +1593,10 @@ predefined_constants = "False", "None", "NotImplemented", "True" +privileged_attributes = [ + "__get_single_item_unchecked__", + ] + unary_operator_functions = { # Unary operations. diff -r ea1e1157afc4 -r 9adc6e8a6fed compiler/ast.py --- a/compiler/ast.py Thu Jul 05 23:41:16 2018 +0200 +++ b/compiler/ast.py Mon Jul 09 17:32:35 2018 +0200 @@ -868,11 +868,15 @@ return "%s %s" % (self.expr, " ".join(map(str, self.quals))) class Getattr(Node): - def __init__(self, expr, attrname, lineno=None): + def __init__(self, expr, attrname, lineno=None, privileged=False): self.expr = expr self.attrname = attrname self.lineno = lineno + # Support privileged internal accesses. + + self.privileged = privileged + def getChildren(self): return self.expr, self.attrname diff -r ea1e1157afc4 -r 9adc6e8a6fed inspector.py --- a/inspector.py Thu Jul 05 23:41:16 2018 +0200 +++ b/inspector.py Mon Jul 09 17:32:35 2018 +0200 @@ -21,7 +21,8 @@ """ from branching import BranchTracker -from common import CommonModule, get_argnames, init_item, predefined_constants +from common import CommonModule, get_argnames, init_item, \ + predefined_constants, privileged_attributes from modules import BasicModule, CacheWritingModule, InspectionNaming from errors import InspectError from referencing import Reference @@ -358,6 +359,16 @@ "Process the given attribute access node 'n'." + path = self.get_namespace_path() + + # Test for access to special privileged attributes. + + if isinstance(n, compiler.ast.Getattr) and \ + n.attrname in privileged_attributes and not n.privileged: + + raise InspectError("Attribute %s is accessed by an unprivileged operation." % + n.attrname, path, n) + # Obtain any completed chain and return the reference to it. name_ref = self.process_attribute_chain(n) @@ -372,8 +383,6 @@ # either being name-based and thus an access rooted on a name, or being # based on some other node and thus an anonymous access of some kind. - path = self.get_namespace_path() - # Start with the the full attribute chain. remaining = self.attrs diff -r ea1e1157afc4 -r 9adc6e8a6fed tests/tuple_unpack_bad.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/tuple_unpack_bad.py Mon Jul 09 17:32:35 2018 +0200 @@ -0,0 +1,9 @@ +def good(t): + a, b, c = t + +def bad(t): + a = t.__get_single_item_unchecked__(0) + +t = 1, 2, 3 +good(t) +bad(t)