コード例 #1
0
def number_global(wrapper, arguments, traverser):
    if not arguments:
        return JSWrapper(0, traverser=traverser)
    arg = traverser._traverse_node(arguments[0])
    try:
        value = float(arg.get_literal_value())
    except (ValueError, TypeError):
        return traverser._build_global(
            name='NaN', entity=predefinedentities.GLOBAL_ENTITIES[u'NaN'])
    return JSWrapper(value, traverser=traverser)
コード例 #2
0
    def definition(wrapper, arguments, traverser):
        """Wraps an XPCOM class instantiation function."""

        if not arguments:
            return None

        traverser._debug('(XPCOM Encountered)')

        if not pretraversed:
            arguments = [traverser._traverse_node(x) for x in arguments]
        argz = arguments[0]

        if not argz.is_global or 'xpcom_map' not in argz.value:
            argz = JSWrapper(traverser=traverser)
            argz.value = {'xpcom_map': lambda: {'value': {}}}

        traverser._debug('(Building XPCOM...)')

        inst = traverser._build_global(
            method, argz.value['xpcom_map']())
        inst.value['overwritable'] = True

        if extend or mutate:
            # FIXME: There should be a way to get this without
            # traversing the call chain twice.
            parent = actions.trace_member(traverser, wrapper['callee']['object'])

            if mutate and not (parent.is_global and
                               isinstance(parent.value, dict) and
                               'value' in parent.value):
                # Assume that the parent object is a first class
                # wrapped native
                parent.value = inst.value

                # FIXME: Only objects marked as global are processed
                # as XPCOM instances
                parent.is_global = True

            if isinstance(parent.value, dict):
                if extend and mutate:
                    if callable(parent.value['value']):
                        parent.value['value'] = \
                            parent.value['value'](t=traverser)

                    parent.value['value'].update(inst.value['value'])
                    return parent

                if extend:
                    inst.value['value'].update(parent.value['value'])

                if mutate:
                    parent.value = inst.value

        return inst
コード例 #3
0
    def definition(wrapper, arguments, traverser):
        """Wraps an XPCOM class instantiation function."""

        if not arguments:
            return None

        traverser._debug('(XPCOM Encountered)')

        if not pretraversed:
            arguments = [traverser._traverse_node(x) for x in arguments]
        argz = arguments[0]

        if not argz.is_global or 'xpcom_map' not in argz.value:
            argz = JSWrapper(traverser=traverser)
            argz.value = {'xpcom_map': lambda: {'value': {}}}

        traverser._debug('(Building XPCOM...)')

        inst = traverser._build_global(method, argz.value['xpcom_map']())
        inst.value['overwritable'] = True

        if extend or mutate:
            # FIXME: There should be a way to get this without
            # traversing the call chain twice.
            parent = actions.trace_member(traverser,
                                          wrapper['callee']['object'])

            if mutate and not (parent.is_global and isinstance(
                    parent.value, dict) and 'value' in parent.value):
                # Assume that the parent object is a first class
                # wrapped native
                parent.value = inst.value

                # FIXME: Only objects marked as global are processed
                # as XPCOM instances
                parent.is_global = True

            if isinstance(parent.value, dict):
                if extend and mutate:
                    if callable(parent.value['value']):
                        parent.value['value'] = \
                            parent.value['value'](t=traverser)

                    parent.value['value'].update(inst.value['value'])
                    return parent

                if extend:
                    inst.value['value'].update(parent.value['value'])

                if mutate:
                    parent.value = inst.value

        return inst
コード例 #4
0
def _define_literal(traverser, node):
    """
    Convert a literal node in the parse tree to its corresponding
    interpreted value.
    """
    value = node['value']
    if isinstance(value, dict):
        return JSWrapper(JSObject(), traverser=traverser, dirty=True)

    wrapper = JSWrapper(value if value is not None else JSLiteral(None),
                        traverser=traverser)
    test_literal(traverser, wrapper)
    return wrapper
コード例 #5
0
def math_log(wrapper, arguments, traverser):
    """Return a better value than the standard python log function."""
    args = [traverser._traverse_node(a) for a in arguments]
    if not args:
        return JSWrapper(0, traverser=traverser)

    arg = actions._get_as_num(args[0].get_literal_value())
    if arg == 0:
        return JSWrapper(float('-inf'), traverser=traverser)

    if arg < 0:
        return JSWrapper(traverser=traverser)

    arg = math.log(arg)
    return JSWrapper(arg, traverser=traverser)
コード例 #6
0
def math_round(wrapper, arguments, traverser):
    """Return a better value than the standard python round function."""
    args = [traverser._traverse_node(a) for a in arguments]
    if not args:
        return JSWrapper(0, traverser=traverser)

    arg = actions._get_as_num(args[0].get_literal_value())
    # Prevent nasty infinity tracebacks.
    if abs(arg) == float('inf'):
        return args[0]

    # Python rounds away from zero, JS rounds "up".
    if arg < 0 and int(arg) != arg:
        arg += 0.0000000000000001
    arg = round(arg)
    return JSWrapper(arg, traverser=traverser)
コード例 #7
0
def _define_obj(traverser, node):
    'Creates a local context object'

    var = JSObject()
    for prop in node['properties']:
        if prop['type'] == 'PrototypeMutation':
            var_name = 'prototype'
        else:
            key = prop['key']
            if key['type'] == 'Literal':
                var_name = key['value']
            elif isinstance(key['name'], basestring):
                var_name = key['name']
            else:
                if 'property' in key['name']:
                    name = key['name']
                else:
                    name = {'property': key['name']}
                var_name = _get_member_exp_property(traverser, name)

        var_value = traverser._traverse_node(prop['value'])
        var.set(var_name, var_value, traverser)

        # TODO: Observe "kind"

    if not isinstance(var, JSWrapper):
        return JSWrapper(var, lazy=True, traverser=traverser)
    var.lazy = True
    return var
コード例 #8
0
    def wrap(wrapper, arguments, traverser):
        passed_args = [traverser._traverse_node(a) for a in arguments]

        params = []
        if not nargs:
            # Handle definite argument lists.
            for type_, def_value in args:
                if passed_args:
                    parg = passed_args[0]
                    passed_args = passed_args[1:]

                    passed_literal = parg.get_literal_value()
                    passed_literal = _process_literal(type_, passed_literal)
                    params.append(passed_literal)
                else:
                    params.append(def_value)
        else:
            # Handle dynamic argument lists.
            for arg in passed_args:
                literal = arg.get_literal_value()
                params.append(_process_literal(args[0], literal))

        traverser._debug('Calling wrapped Python function with: (%s)' %
                         ', '.join(map(str, params)))
        try:
            output = func(*params)
        except (ValueError, TypeError, OverflowError):
            # If we cannot compute output, just return nothing.
            output = None

        return JSWrapper(output, traverser=traverser)
コード例 #9
0
def _expr_binary(traverser, node):
    'Evaluates a BinaryExpression node.'

    traverser.debug_level += 1

    # Select the proper operator.
    operator = node['operator']
    traverser._debug('BIN_OPERATOR>>%s' % operator)

    # Traverse the left half of the binary expression.
    with traverser._debug('BIN_EXP>>l-value'):
        if (node['left']['type'] == 'BinaryExpression'
                and '__traversal' not in node['left']):
            # Process the left branch of the binary expression directly. This
            # keeps the recursion cap in line and speeds up processing of
            # large chains of binary expressions.
            left = _expr_binary(traverser, node['left'])
            node['left']['__traversal'] = left
        else:
            left = traverser._traverse_node(node['left'])

    # Traverse the right half of the binary expression.
    with traverser._debug('BIN_EXP>>r-value'):
        if (operator == 'instanceof' and node['right']['type'] == 'Identifier'
                and node['right']['name'] == 'Function'):
            # We make an exception for instanceof's r-value if it's a
            # dangerous global, specifically Function.
            return JSWrapper(True, traverser=traverser)
        else:
            right = traverser._traverse_node(node['right'])
            traverser._debug('Is dirty? %r' % right.dirty, 1)

    return _binary_op(operator, left, right, traverser)
コード例 #10
0
def _function(traverser, node):
    'Prevents code duplication'

    def wrap(traverser, node):
        me = JSObject()

        traverser.function_collection.append([])

        # Replace the current context with a prototypeable JS object.
        traverser._pop_context()
        me.type_ = 'default'  # Treat the function as a normal object.
        traverser._push_context(me)
        traverser._debug('THIS_PUSH')
        traverser.this_stack.append(me)  # Allow references to "this"

        # Declare parameters in the local scope
        params = []
        for param in node['params']:
            if param['type'] == 'Identifier':
                params.append(param['name'])
            elif param['type'] == 'ArrayPattern':
                for element in param['elements']:
                    # Array destructuring in function prototypes? LOL!
                    if element is None or element['type'] != 'Identifier':
                        continue
                    params.append(element['name'])

        local_context = traverser._peek_context(1)
        for param in params:
            var = JSWrapper(lazy=True, traverser=traverser)

            # We can assume that the params are static because we don't care
            # about what calls the function. We want to know whether the
            # function solely returns static values. If so, it is a static
            # function.
            local_context.set(param, var)

        traverser._traverse_node(node['body'])

        # Since we need to manually manage the "this" stack, pop off that
        # context.
        traverser._debug('THIS_POP')
        traverser.this_stack.pop()

        # Call all of the function collection's members to traverse all of the
        # child functions.
        func_coll = traverser.function_collection.pop()
        for func in func_coll:
            func()

    # Put the function off for traversal at the end of the current block scope.
    traverser.function_collection[-1].append(partial(wrap, traverser, node))

    return JSWrapper(traverser=traverser, callable=True, dirty=True)
コード例 #11
0
ファイル: actions.py プロジェクト: l-hedgehog/amo-validator
def _new(traverser, node):
    "Returns a new copy of a node."

    # We don't actually process the arguments as part of the flow because of
    # the Angry T-Rex effect. For now, we just traverse them to ensure they
    # don't contain anything dangerous.
    args = node["arguments"]
    if isinstance(args, list):
        for arg in args:
            traverser._traverse_node(arg, source="arguments")
    else:
        traverser._traverse_node(args)

    elem = traverser._traverse_node(node["callee"])
    if not isinstance(elem, JSWrapper):
        elem = JSWrapper(elem, traverser=traverser)
    if elem.is_global:
        traverser._debug("Making overwritable")
        elem.value = copy.deepcopy(elem.value)
        elem.value["overwritable"] = True
    return elem
コード例 #12
0
def nsIJSON_deprec(wrapper, arguments, traverser):
    """Throw a compatibility error about removed XPCOM methods."""
    traverser.notice(
        err_id=('testcases_javascript_calldefinitions', 'nsIJSON', 'deprec'),
        notice='Deprecated nsIJSON methods in use.',
        description=('The `encode` and `decode` methods in nsIJSON have been '
                     'deprecated in Gecko 7. You can use the methods in the '
                     'global JSON object instead. See %s for more '
                     'information.') %
        'https://developer.mozilla.org/En/Using_native_JSON')

    return JSWrapper(JSObject(), traverser=traverser, dirty=True)
コード例 #13
0
def _ident(traverser, node):
    'Initiates an object lookup on the traverser based on an identifier token'

    name = node['name']

    # Ban bits like "newThread"
    test_identifier(traverser, name)

    if traverser._is_defined(name):
        return traverser._seek_variable(name)

    return JSWrapper(JSObject(), traverser=traverser, dirty=True)
コード例 #14
0
def _new(traverser, node):
    'Returns a new copy of a node.'

    # We don't actually process the arguments as part of the flow because of
    # the Angry T-Rex effect. For now, we just traverse them to ensure they
    # don't contain anything dangerous.
    args = node['arguments']
    if isinstance(args, list):
        for arg in args:
            traverser._traverse_node(arg, source='arguments')
    else:
        traverser._traverse_node(args)

    elem = traverser._traverse_node(node['callee'])
    if not isinstance(elem, JSWrapper):
        elem = JSWrapper(elem, traverser=traverser)
    if elem.is_global:
        traverser._debug('Making overwritable')
        elem.value = deepcopy(elem.value)
        elem.value['overwritable'] = True
    return elem
コード例 #15
0
ファイル: actions.py プロジェクト: l-hedgehog/amo-validator
def _expand_globals(traverser, node):
    """Expands a global object that has a lambda value."""

    if node.is_global and callable(node.value.get("value")):
        result = node.value["value"](traverser)
        if isinstance(result, dict):
            output = traverser._build_global("--", result)
        elif isinstance(result, JSWrapper):
            output = result
        else:
            output = JSWrapper(result, traverser)

        # Set the node context.
        if "context" in node.value:
            traverser._debug("CONTEXT>>%s" % node.value["context"])
            output.context = node.value["context"]
        else:
            traverser._debug("CONTEXT>>INHERITED")
            output.context = node.context

        return output

    return node
コード例 #16
0
def _expand_globals(traverser, node):
    """Expands a global object that has a lambda value."""

    if node.is_global and callable(node.value.get('value')):
        result = node.value['value'](traverser)
        if isinstance(result, dict):
            output = traverser._build_global('--', result)
        elif isinstance(result, JSWrapper):
            output = result
        else:
            output = JSWrapper(result, traverser)

        # Set the node context.
        if 'context' in node.value:
            traverser._debug('CONTEXT>>%s' % node.value['context'])
            output.context = node.value['context']
        else:
            traverser._debug('CONTEXT>>INHERITED')
            output.context = node.context

        return output

    return node
コード例 #17
0
ファイル: actions.py プロジェクト: Sancus/amo-validator
def _expand_globals(traverser, node):
    """Expands a global object that has a lambda value."""

    if node.is_global and callable(node.value.get('value')):
        result = node.value['value'](traverser)
        if isinstance(result, dict):
            output = traverser._build_global('--', result)
        elif isinstance(result, JSWrapper):
            output = result
        else:
            output = JSWrapper(result, traverser)

        # Set the node context.
        if 'context' in node.value:
            traverser._debug('CONTEXT>>%s' % node.value['context'])
            output.context = node.value['context']
        else:
            traverser._debug('CONTEXT>>INHERITED')
            output.context = node.context

        return output

    return node
コード例 #18
0
def _call_create_pref(a, t, e):
    """
    Handler for pref() and user_pref() calls in defaults/preferences/*.js files
    to ensure that they don't touch preferences outside of the "extensions."
    branch.
    """

    # We really need to clean up the arguments passed to these functions.
    traverser = t.im_self

    if not traverser.filename.startswith('defaults/preferences/') or not a:
        return

    instanceactions.set_preference(
        JSWrapper(JSLiteral(None), traverser=traverser), a, traverser)

    value = _get_as_str(t(a[0]))
    return test_preference(value)
コード例 #19
0
def js_unwrap(wrapper, arguments, traverser):
    """Return the unwrapped variant of an unwrapped JSObject."""
    if not arguments:
        traverser._debug('UNWRAP:NO ARGS')
        return

    traverser._debug('UNWRAPPING OBJECT')
    obj = traverser._traverse_node(arguments[0])
    if obj.value is None:
        traverser._debug('UNWRAPPING OBJECT>>NOTHING TO UNWRAP')
        return JSWrapper(JSObject(unwrapped=True), traverser=traverser)

    if obj.is_global:
        obj.value['is_unwrapped'] = True
    else:
        obj.value.is_unwrapped = True

    return obj
コード例 #20
0
def _expr_unary(traverser, node):
    """Evaluate a UnaryExpression node."""

    expr = traverser._traverse_node(node['argument'])
    expr_lit = expr.get_literal_value()
    expr_num = _get_as_num(expr_lit)

    operators = {'-': lambda: -1 * expr_num,
                 '+': lambda: expr_num,
                 '!': lambda: not expr_lit,
                 '~': lambda: -1 * (expr_num + 1),
                 'void': lambda: None,
                 'typeof': lambda: _expr_unary_typeof(expr),
                 'delete': lambda: None}  # We never want to empty the context
    if node['operator'] in operators:
        output = operators[node['operator']]()
    else:
        output = None

    if not isinstance(output, JSWrapper):
        output = JSWrapper(output, traverser=traverser)
    return output
コード例 #21
0
def js_wrap(wrapper, arguments, traverser):
    """Return the wrapped variant of an unwrapped JSObject."""
    if not arguments:
        traverser._debug('WRAP:NO ARGS')
        return

    traverser._debug('WRAPPING OBJECT')
    obj = traverser._traverse_node(arguments[0])
    if obj.value is None:
        traverser._debug('WRAPPING OBJECT>>NOTHING TO WRAP')
        return JSWrapper(JSObject(), traverser=traverser)

    if len(arguments) > 1:
        traverser.warning(
            err_id=('testcases_js_xpcom', 'xpcnativewrapper', 'shallow'),
            warning='Shallow XPCOM wrappers should not be used',
            description='Shallow XPCOM wrappers are seldom necessary and '
            'should not be used. Please use deep wrappers '
            'instead.',
            signing_help='Extensions making use of shallow wrappers will not '
            'be accepted for automated signing. Please remove '
            'the second and subsequent arguments of any calls '
            'to `XPCNativeWrapper`, as well as any code which '
            'applies `XPCNativeWrapper` to properties obtained '
            'from these shallowly wrapped objects.',
            signing_severity='high')
        # Do not mark shallow wrappers as not unwrapped.
        return obj

    if obj.is_global:
        # Why are we changing the original object? XPCNativeWrapper
        # does not alter its arguments.
        obj.value['is_unwrapped'] = False
    else:
        obj.value.is_unwrapped = False

    return obj
コード例 #22
0
def _call_expression(traverser, node):
    args = node['arguments']
    for arg in args:
        traverser._traverse_node(arg, source='arguments')

    member = traverser._traverse_node(node['callee'])

    if (traverser.filename.startswith('defaults/preferences/')
            and ('name' not in node['callee']
                 or node['callee']['name'] not in (u'pref', u'user_pref'))):

        traverser.err.warning(
            err_id=('testcases_javascript_actions', '_call_expression',
                    'complex_prefs_defaults_code'),
            warning='Complex code should not appear in preference defaults '
            'files',
            description="Calls to functions other than 'pref' and 'user_pref' "
            'should not appear in defaults/preferences/ files.',
            filename=traverser.filename,
            line=traverser.line,
            column=traverser.position,
            context=traverser.context)

    if member.is_global:
        if callable(member.value.get('dangerous', None)):
            result = member.value['dangerous'](a=args,
                                               t=traverser._traverse_node,
                                               e=traverser.err)
            name = member.value.get('name', '')

            if result and name:
                kwargs = {
                    'err_id': ('testcases_javascript_actions',
                               '_call_expression', 'called_dangerous_global'),
                    'warning':
                    '`%s` called in potentially dangerous manner' %
                    member.value['name'],
                    'description':
                    'The global `%s` function was called using a set '
                    'of dangerous parameters. Calls of this nature '
                    'are deprecated.' % member.value['name']
                }

                if isinstance(result, DESCRIPTION_TYPES):
                    kwargs['description'] = result
                elif isinstance(result, dict):
                    kwargs.update(result)

                traverser.warning(**kwargs)

        if callable(member.value.get('forbidden', None)):
            result = member.value['forbidden'](a=args,
                                               t=traverser._traverse_node,
                                               e=traverser.err)
            name = member.value.get('name', '')

            if result and name:
                kwargs = {
                    'err_id': ('testcases_javascript_actions',
                               '_call_expression', 'called_forbidden_global'),
                    'warning':
                    ' Forbidden `%s` called' % member.value['name'],
                    'description':
                    'The forbidden global `%s` function was called.' %
                    member.value['name']
                }

                if isinstance(result, DESCRIPTION_TYPES):
                    kwargs['description'] = result
                elif isinstance(result, dict):
                    kwargs.update(result)

                traverser.error(**kwargs)

    elif (node['callee']['type'] == 'MemberExpression'
          and node['callee']['property']['type'] == 'Identifier'):

        # If we can identify the function being called on any member of any
        # instance, we can use that to either generate an output value or test
        # for additional conditions.
        identifier_name = node['callee']['property']['name']
        if identifier_name in instanceactions.INSTANCE_DEFINITIONS:
            result = instanceactions.INSTANCE_DEFINITIONS[identifier_name](
                args, traverser, node, wrapper=member)
            return result

    if member.is_global and 'return' in member.value:
        if 'object' in node['callee']:
            member.parent = trace_member(traverser, node['callee']['object'])

        return member.value['return'](wrapper=member,
                                      arguments=args,
                                      traverser=traverser)
    return JSWrapper(JSObject(), dirty=True, traverser=traverser)
コード例 #23
0
def array_global(wrapper, arguments, traverser):
    output = JSArray()
    if arguments:
        output.elements = [traverser._traverse_node(a) for a in arguments]
    return JSWrapper(output, traverser=traverser)
コード例 #24
0
def _expr_assignment(traverser, node):
    """Evaluate an AssignmentExpression node."""

    traverser._debug('ASSIGNMENT_EXPRESSION')
    traverser.debug_level += 1

    traverser._debug('ASSIGNMENT>>PARSING RIGHT')
    right = traverser._traverse_node(node['right'])
    right = JSWrapper(right, traverser=traverser)

    # Treat direct assignment different than augmented assignment.
    if node['operator'] == '=':
        from predefinedentities import GLOBAL_ENTITIES, is_shared_scope

        global_overwrite = False
        readonly_value = is_shared_scope(traverser)

        node_left = node['left']
        traverser._debug('ASSIGNMENT:DIRECT(%s)' % node_left['type'])

        if node_left['type'] == 'Identifier':
            # Identifiers just need the ID name and a value to push.
            # Raise a global overwrite issue if the identifier is global.
            global_overwrite = traverser._is_global(node_left['name'])

            # Get the readonly attribute and store its value if is_global
            if global_overwrite:
                global_dict = GLOBAL_ENTITIES[node_left['name']]
                if 'readonly' in global_dict:
                    readonly_value = global_dict['readonly']

            traverser._declare_variable(node_left['name'], right, type_='glob')
        elif node_left['type'] == 'MemberExpression':
            member_object = trace_member(traverser,
                                         node_left['object'],
                                         instantiate=True)
            global_overwrite = (member_object.is_global and
                                not ('overwritable' in member_object.value
                                     and member_object.value['overwritable']))
            member_property = _get_member_exp_property(traverser, node_left)
            traverser._debug('ASSIGNMENT:MEMBER_PROPERTY(%s)' %
                             member_property)
            traverser._debug('ASSIGNMENT:GLOB_OV::%s' % global_overwrite)

            # Don't do the assignment if we're facing a global.
            if not member_object.is_global:
                if member_object.value is None:
                    member_object.value = JSObject()

                if not member_object.is_global:
                    member_object.value.set(member_property, right, traverser)
                else:
                    # It's probably better to do nothing.
                    pass

            elif 'value' in member_object.value:
                member_object_value = _expand_globals(traverser,
                                                      member_object).value
                if member_property in member_object_value['value']:

                    # If it's a global and the actual member exists, test
                    # whether it can be safely overwritten.
                    member = member_object_value['value'][member_property]
                    if 'readonly' in member:
                        global_overwrite = True
                        readonly_value = member['readonly']

        traverser._debug('ASSIGNMENT:DIRECT:GLOB_OVERWRITE %s' %
                         global_overwrite)
        traverser._debug('ASSIGNMENT:DIRECT:READONLY %r' % readonly_value)

        if callable(readonly_value):
            readonly_value = readonly_value(traverser, right, node['right'])

        if readonly_value and global_overwrite:

            kwargs = dict(
                err_id=('testcases_javascript_actions', '_expr_assignment',
                        'global_overwrite'),
                warning='Global variable overwrite',
                description='An attempt was made to overwrite a global '
                'variable in some JavaScript code.')

            if isinstance(readonly_value, DESCRIPTION_TYPES):
                kwargs['description'] = readonly_value
            elif isinstance(readonly_value, dict):
                kwargs.update(readonly_value)

            traverser.warning(**kwargs)

        return right

    lit_right = right.get_literal_value()

    traverser._debug('ASSIGNMENT>>PARSING LEFT')
    left = traverser._traverse_node(node['left'])
    traverser._debug('ASSIGNMENT>>DONE PARSING LEFT')
    traverser.debug_level -= 1

    if isinstance(left, JSWrapper):
        if left.dirty:
            return left

        lit_left = left.get_literal_value()
        token = node['operator']

        # Don't perform an operation on None. Python freaks out
        if lit_left is None:
            lit_left = 0
        if lit_right is None:
            lit_right = 0

        # Give them default values so we have them in scope.
        gleft, gright = 0, 0

        # All of the assignment operators
        operators = {
            '=': lambda: right,
            '+=': lambda: lit_left + lit_right,
            '-=': lambda: gleft - gright,
            '*=': lambda: gleft * gright,
            '/=': lambda: 0 if gright == 0 else (gleft / gright),
            '%=': lambda: 0 if gright == 0 else (gleft % gright),
            '<<=': lambda: int(gleft) << int(gright),
            '>>=': lambda: int(gleft) >> int(gright),
            '>>>=': lambda: float(abs(int(gleft)) >> gright),
            '|=': lambda: int(gleft) | int(gright),
            '^=': lambda: int(gleft) ^ int(gright),
            '&=': lambda: int(gleft) & int(gright)
        }

        # If we're modifying a non-numeric type with a numeric operator, return
        # NaN.
        if (not isinstance(lit_left, NUMERIC_TYPES)
                and token in NUMERIC_OPERATORS):
            left.set_value(get_NaN(traverser), traverser=traverser)
            return left

        # If either side of the assignment operator is a string, both sides
        # need to be casted to strings first.
        if (isinstance(lit_left, types.StringTypes)
                or isinstance(lit_right, types.StringTypes)):
            lit_left = _get_as_str(lit_left)
            lit_right = _get_as_str(lit_right)

        gleft, gright = _get_as_num(left), _get_as_num(right)

        traverser._debug('ASSIGNMENT>>OPERATION:%s' % token)
        if token not in operators:
            # We don't support that operator. (yet?)
            traverser._debug('ASSIGNMENT>>OPERATOR NOT FOUND', 1)
            return left
        elif token in ('<<=', '>>=', '>>>=') and gright < 0:
            # The user is doing weird bitshifting that will return 0 in JS but
            # not in Python.
            left.set_value(0, traverser=traverser)
            return left
        elif (token in ('<<=', '>>=', '>>>=', '|=', '^=', '&=')
              and (abs(gleft) == float('inf') or abs(gright) == float('inf'))):
            # Don't bother handling infinity for integer-converted operations.
            left.set_value(get_NaN(traverser), traverser=traverser)
            return left

        traverser._debug(
            'ASSIGNMENT::L-value global? (%s)' %
            ('Y' if left.is_global else 'N'), 1)
        try:
            new_value = operators[token]()
        except Exception:
            traverser.system_error(exc_info=sys.exc_info())
            new_value = None

        # Cap the length of analyzed strings.
        if (isinstance(new_value, types.StringTypes)
                and len(new_value) > MAX_STR_SIZE):
            new_value = new_value[:MAX_STR_SIZE]

        traverser._debug('ASSIGNMENT::New value >> %s' % new_value, 1)
        left.set_value(new_value, traverser=traverser)
        return left

    # Though it would otherwise be a syntax error, we say that 4=5 should
    # evaluate out to 5.
    return right
コード例 #25
0
def math_random(wrapper, arguments, traverser):
    """Return a "random" value for Math.random()."""
    return JSWrapper(0.5, traverser=traverser)
コード例 #26
0
ファイル: actions.py プロジェクト: l-hedgehog/amo-validator
def _expr_assignment(traverser, node):
    """Evaluate an AssignmentExpression node."""

    traverser._debug("ASSIGNMENT_EXPRESSION")
    traverser.debug_level += 1

    traverser._debug("ASSIGNMENT>>PARSING RIGHT")
    right = traverser._traverse_node(node["right"])
    right = JSWrapper(right, traverser=traverser)

    # Treat direct assignment different than augmented assignment.
    if node["operator"] == "=":
        from predefinedentities import GLOBAL_ENTITIES, is_shared_scope

        global_overwrite = False
        readonly_value = is_shared_scope(traverser)

        node_left = node["left"]
        traverser._debug("ASSIGNMENT:DIRECT(%s)" % node_left["type"])

        if node_left["type"] == "Identifier":
            # Identifiers just need the ID name and a value to push.
            # Raise a global overwrite issue if the identifier is global.
            global_overwrite = traverser._is_global(node_left["name"])

            # Get the readonly attribute and store its value if is_global
            if global_overwrite:
                global_dict = GLOBAL_ENTITIES[node_left["name"]]
                if "readonly" in global_dict:
                    readonly_value = global_dict["readonly"]

            traverser._declare_variable(node_left["name"], right, type_="glob")
        elif node_left["type"] == "MemberExpression":
            member_object = trace_member(traverser, node_left["object"],
                                         instantiate=True)
            global_overwrite = (member_object.is_global and
                                not ("overwritable" in member_object.value and
                                     member_object.value["overwritable"]))
            member_property = _get_member_exp_property(traverser, node_left)
            traverser._debug("ASSIGNMENT:MEMBER_PROPERTY(%s)"
                             % member_property)
            traverser._debug("ASSIGNMENT:GLOB_OV::%s" % global_overwrite)

            # Don't do the assignment if we're facing a global.
            if not member_object.is_global:
                if member_object.value is None:
                    member_object.value = JSObject()

                if not member_object.is_global:
                    member_object.value.set(member_property, right, traverser)
                else:
                    # It's probably better to do nothing.
                    pass

            elif "value" in member_object.value:
                member_object_value = _expand_globals(traverser,
                                                      member_object).value
                if member_property in member_object_value["value"]:

                    # If it's a global and the actual member exists, test
                    # whether it can be safely overwritten.
                    member = member_object_value["value"][member_property]
                    if "readonly" in member:
                        global_overwrite = True
                        readonly_value = member["readonly"]

        traverser._debug("ASSIGNMENT:DIRECT:GLOB_OVERWRITE %s" %
                         global_overwrite)
        traverser._debug("ASSIGNMENT:DIRECT:READONLY %r" %
                         readonly_value)

        if callable(readonly_value):
            readonly_value = readonly_value(traverser, right, node["right"])

        if readonly_value and global_overwrite:

            kwargs = dict(
                err_id=("testcases_javascript_actions",
                        "_expr_assignment",
                        "global_overwrite"),
                warning="Global variable overwrite",
                description="An attempt was made to overwrite a global "
                            "variable in some JavaScript code.")

            if isinstance(readonly_value, DESCRIPTION_TYPES):
                kwargs["description"] = readonly_value
            elif isinstance(readonly_value, dict):
                kwargs.update(readonly_value)

            traverser.warning(**kwargs)

        return right

    lit_right = right.get_literal_value()

    traverser._debug("ASSIGNMENT>>PARSING LEFT")
    left = traverser._traverse_node(node["left"])
    traverser._debug("ASSIGNMENT>>DONE PARSING LEFT")
    traverser.debug_level -= 1

    if isinstance(left, JSWrapper):
        if left.dirty:
            return left

        lit_left = left.get_literal_value()
        token = node["operator"]

        # Don't perform an operation on None. Python freaks out
        if lit_left is None:
            lit_left = 0
        if lit_right is None:
            lit_right = 0

        # Give them default values so we have them in scope.
        gleft, gright = 0, 0

        # All of the assignment operators
        operators = {"=": lambda: right,
                     "+=": lambda: lit_left + lit_right,
                     "-=": lambda: gleft - gright,
                     "*=": lambda: gleft * gright,
                     "/=": lambda: 0 if gright == 0 else (gleft / gright),
                     "%=": lambda: 0 if gright == 0 else (gleft % gright),
                     "<<=": lambda: int(gleft) << int(gright),
                     ">>=": lambda: int(gleft) >> int(gright),
                     ">>>=": lambda: float(abs(int(gleft)) >> gright),
                     "|=": lambda: int(gleft) | int(gright),
                     "^=": lambda: int(gleft) ^ int(gright),
                     "&=": lambda: int(gleft) & int(gright)}

        # If we're modifying a non-numeric type with a numeric operator, return
        # NaN.
        if (not isinstance(lit_left, NUMERIC_TYPES) and
                token in NUMERIC_OPERATORS):
            left.set_value(get_NaN(traverser), traverser=traverser)
            return left

        # If either side of the assignment operator is a string, both sides
        # need to be casted to strings first.
        if (isinstance(lit_left, types.StringTypes) or
                isinstance(lit_right, types.StringTypes)):
            lit_left = _get_as_str(lit_left)
            lit_right = _get_as_str(lit_right)

        gleft, gright = _get_as_num(left), _get_as_num(right)

        traverser._debug("ASSIGNMENT>>OPERATION:%s" % token)
        if token not in operators:
            # We don't support that operator. (yet?)
            traverser._debug("ASSIGNMENT>>OPERATOR NOT FOUND", 1)
            return left
        elif token in ("<<=", ">>=", ">>>=") and gright < 0:
            # The user is doing weird bitshifting that will return 0 in JS but
            # not in Python.
            left.set_value(0, traverser=traverser)
            return left
        elif (token in ("<<=", ">>=", ">>>=", "|=", "^=", "&=") and
              (abs(gleft) == float('inf') or abs(gright) == float('inf'))):
            # Don't bother handling infinity for integer-converted operations.
            left.set_value(get_NaN(traverser), traverser=traverser)
            return left

        traverser._debug("ASSIGNMENT::L-value global? (%s)" %
                         ("Y" if left.is_global else "N"), 1)
        try:
            new_value = operators[token]()
        except Exception:
            new_value = None

        # Cap the length of analyzed strings.
        if (isinstance(new_value, types.StringTypes) and
                len(new_value) > MAX_STR_SIZE):
            new_value = new_value[:MAX_STR_SIZE]

        traverser._debug("ASSIGNMENT::New value >> %s" % new_value, 1)
        left.set_value(new_value, traverser=traverser)
        return left

    # Though it would otherwise be a syntax error, we say that 4=5 should
    # evaluate out to 5.
    return right
コード例 #27
0
ファイル: actions.py プロジェクト: Sancus/amo-validator
def _define_var(traverser, node):
    'Creates a local context variable'

    traverser._debug('VARIABLE_DECLARATION')
    traverser.debug_level += 1

    declarations = (node['declarations'] if 'declarations' in node
                    else node['head'])

    kind = node.get('kind', 'let')
    for declaration in declarations:

        # It could be deconstruction of variables :(
        if declaration['id']['type'] == 'ArrayPattern':

            vars = []
            for element in declaration['id']['elements']:
                # NOTE : Multi-level array destructuring sucks. Maybe implement
                # it someday if you're bored, but it's so rarely used and it's
                # so utterly complex, there's probably no need to ever code it
                # up.
                if element is None or element['type'] != 'Identifier':
                    vars.append(None)
                    continue
                vars.append(element['name'])

            # The variables are not initialized
            if declaration['init'] is None:
                # Simple instantiation; no initialization
                for var in vars:
                    if not var:
                        continue
                    traverser._declare_variable(var, None)

            # The variables are declared inline
            elif declaration['init']['type'] == 'ArrayPattern':
                # TODO : Test to make sure len(values) == len(vars)
                for value in declaration['init']['elements']:
                    if vars[0]:
                        traverser._declare_variable(
                            vars[0], JSWrapper(traverser._traverse_node(value),
                                               traverser=traverser))
                    vars = vars[1:]  # Pop off the first value

            # It's being assigned by a JSArray (presumably)
            elif declaration['init']['type'] == 'ArrayExpression':

                assigner = traverser._traverse_node(declaration['init'])
                for value in assigner.value.elements:
                    if vars[0]:
                        traverser._declare_variable(vars[0], value)
                    vars = vars[1:]

        elif declaration['id']['type'] == 'ObjectPattern':

            init = traverser._traverse_node(declaration['init'])

            def _proc_objpattern(init_obj, properties):
                for prop in properties:
                    # Get the name of the init obj's member
                    if prop['key']['type'] == 'Literal':
                        prop_name = prop['key']['value']
                    elif prop['key']['type'] == 'Identifier':
                        prop_name = prop['key']['name']
                    else:
                        continue

                    if prop['value']['type'] == 'Identifier':
                        traverser._declare_variable(
                            prop['value']['name'],
                            init_obj.get(traverser, prop_name))
                    elif prop['value']['type'] == 'ObjectPattern':
                        _proc_objpattern(init_obj.get(traverser, prop_name),
                                         prop['value']['properties'])

            if init is not None:
                _proc_objpattern(init_obj=init,
                                 properties=declaration['id']['properties'])

        else:
            var_name = declaration['id']['name']
            traverser._debug('NAME>>%s' % var_name)

            var_value = traverser._traverse_node(declaration['init'])
            traverser._debug('VALUE>>%s' % (var_value.output()
                                            if var_value is not None
                                            else 'None'))

            if not isinstance(var_value, JSWrapper):
                var = JSWrapper(value=var_value,
                                const=kind == 'const',
                                traverser=traverser)
            else:
                var = var_value
                var.const = kind == 'const'

            traverser._declare_variable(var_name, var, type_=kind)

    if 'body' in node:
        traverser._traverse_node(node['body'])

    traverser.debug_level -= 1

    # The "Declarations" branch contains custom elements.
    return True
コード例 #28
0
def _binary_op(operator, left, right, traverser):
    """Perform a binary operation on two pre-traversed nodes."""

    # Dirty l or r values mean we can skip the expression. A dirty value
    # indicates that a lazy operation took place that introduced some
    # nondeterminacy.
    # FIXME(Kris): We should process these as if they're strings anyway.
    if left.dirty:
        return left
    elif right.dirty:
        return right

    # Binary expressions are only executed on literals.
    left = left.get_literal_value()
    right_wrap = right
    right = right.get_literal_value()

    # Coerce the literals to numbers for numeric operations.
    gleft = _get_as_num(left)
    gright = _get_as_num(right)

    operators = {
        '==': lambda: left == right or gleft == gright,
        '!=': lambda: left != right,
        '===': lambda: left == right,  # Be flexible.
        '!==': lambda: type(left) != type(right) or left != right,
        '>': lambda: left > right,
        '<': lambda: left < right,
        '<=': lambda: left <= right,
        '>=': lambda: left >= right,
        '<<': lambda: int(gleft) << int(gright),
        '>>': lambda: int(gleft) >> int(gright),
        '>>>': lambda: float(abs(int(gleft)) >> int(gright)),
        '+': lambda: left + right,
        '-': lambda: gleft - gright,
        '*': lambda: gleft * gright,
        '/': lambda: 0 if gright == 0 else (gleft / gright),
        '%': lambda: 0 if gright == 0 else (gleft % gright),
        'in': lambda: right_wrap.contains(left),
        # TODO : implement instanceof
        # FIXME(Kris): Treat instanceof the same as `QueryInterface`
    }

    output = None
    if (operator in ('>>', '<<', '>>>')
            and (left is None or right is None or gright < 0)):
        output = False
    elif operator in operators:
        # Concatenation can be silly, so always turn undefineds into empty
        # strings and if there are strings, make everything strings.
        if operator == '+':
            if left is None:
                left = ''
            if right is None:
                right = ''
            if isinstance(left, basestring) or isinstance(right, basestring):
                left = _get_as_str(left)
                right = _get_as_str(right)

        # Don't even bother handling infinity if it's a numeric computation.
        if (operator in ('<<', '>>', '>>>') and
            (abs(gleft) == float('inf') or abs(gright) == float('inf'))):
            return get_NaN(traverser)

        try:
            output = operators[operator]()
        except Exception:
            traverser.system_error(exc_info=sys.exc_info())
            output = None

        # Cap the length of analyzed strings.
        if (isinstance(output, types.StringTypes)
                and len(output) > MAX_STR_SIZE):
            output = output[:MAX_STR_SIZE]

        wrapper = JSWrapper(output, traverser=traverser)

        # Test the newly-created literal for dangerous values.
        # This may cause duplicate warnings for strings which
        # already match a dangerous value prior to concatenation.
        test_literal(traverser, wrapper)

        return wrapper

    return JSWrapper(output, traverser=traverser)
コード例 #29
0
def string_global(wrapper, arguments, traverser):
    if not arguments:
        return JSWrapper('', traverser=traverser)
    arg = traverser._traverse_node(arguments[0])
    value = actions._get_as_str(arg.get_literal_value())
    return JSWrapper(value, traverser=traverser)
コード例 #30
0
def trace_member(traverser, node, instantiate=False):
    'Traces a MemberExpression and returns the appropriate object'

    traverser._debug('TESTING>>%s' % node['type'])
    if node['type'] == 'MemberExpression':
        # x.y or x[y]
        # x = base
        base = trace_member(traverser, node['object'], instantiate)
        base = _expand_globals(traverser, base)

        identifier = _get_member_exp_property(traverser, node)

        # Handle the various global entity properties.
        if base.is_global:
            # If we've got an XPCOM wildcard, return a copy of the entity.
            if 'xpcom_wildcard' in base.value:
                traverser._debug('MEMBER_EXP>>XPCOM_WILDCARD')

                from predefinedentities import CONTRACT_ENTITIES
                if identifier in CONTRACT_ENTITIES:
                    kw = dict(err_id=('js', 'actions', 'dangerous_contract'),
                              warning='Dangerous XPCOM contract ID')
                    kw.update(CONTRACT_ENTITIES[identifier])

                    traverser.warning(**kw)

                base.value = base.value.copy()
                del base.value['xpcom_wildcard']
                return base

        test_identifier(traverser, identifier)

        traverser._debug('MEMBER_EXP>>PROPERTY: %s' % identifier)
        output = base.get(traverser=traverser,
                          instantiate=instantiate,
                          name=identifier)
        output.context = base.context

        if base.is_global:
            # In the cases of XPCOM objects, methods generally
            # remain bound to their parent objects, even when called
            # indirectly.
            output.parent = base
        return output

    elif node['type'] == 'Identifier':
        traverser._debug('MEMBER_EXP>>ROOT:IDENTIFIER')
        test_identifier(traverser, node['name'])

        # If we're supposed to instantiate the object and it doesn't already
        # exist, instantitate the object.
        if instantiate and not traverser._is_defined(node['name']):
            output = JSWrapper(JSObject(), traverser=traverser)
            traverser.contexts[0].set(node['name'], output)
        else:
            output = traverser._seek_variable(node['name'])

        return _expand_globals(traverser, output)
    else:
        traverser._debug('MEMBER_EXP>>ROOT:EXPRESSION')
        # It's an expression, so just try your damndest.
        return traverser._traverse_node(node)
コード例 #31
0
ファイル: actions.py プロジェクト: l-hedgehog/amo-validator
def _define_var(traverser, node):
    "Creates a local context variable"

    traverser._debug("VARIABLE_DECLARATION")
    traverser.debug_level += 1

    declarations = (node["declarations"] if "declarations" in node
                    else node["head"])

    kind = node.get("kind", "let")
    for declaration in declarations:

        # It could be deconstruction of variables :(
        if declaration["id"]["type"] == "ArrayPattern":

            vars = []
            for element in declaration["id"]["elements"]:
                # NOTE : Multi-level array destructuring sucks. Maybe implement
                # it someday if you're bored, but it's so rarely used and it's
                # so utterly complex, there's probably no need to ever code it
                # up.
                if element is None or element["type"] != "Identifier":
                    vars.append(None)
                    continue
                vars.append(element["name"])

            # The variables are not initialized
            if declaration["init"] is None:
                # Simple instantiation; no initialization
                for var in vars:
                    if not var:
                        continue
                    traverser._declare_variable(var, None)

            # The variables are declared inline
            elif declaration["init"]["type"] == "ArrayPattern":
                # TODO : Test to make sure len(values) == len(vars)
                for value in declaration["init"]["elements"]:
                    if vars[0]:
                        traverser._declare_variable(
                            vars[0], JSWrapper(traverser._traverse_node(value),
                                               traverser=traverser))
                    vars = vars[1:]  # Pop off the first value

            # It's being assigned by a JSArray (presumably)
            elif declaration["init"]["type"] == "ArrayExpression":

                assigner = traverser._traverse_node(declaration["init"])
                for value in assigner.value.elements:
                    if vars[0]:
                        traverser._declare_variable(vars[0], value)
                    vars = vars[1:]

        elif declaration["id"]["type"] == "ObjectPattern":

            init = traverser._traverse_node(declaration["init"])

            def _proc_objpattern(init_obj, properties):
                for prop in properties:
                    # Get the name of the init obj's member
                    if prop["key"]["type"] == "Literal":
                        prop_name = prop["key"]["value"]
                    elif prop["key"]["type"] == "Identifier":
                        prop_name = prop["key"]["name"]
                    else:
                        continue

                    if prop["value"]["type"] == "Identifier":
                        traverser._declare_variable(
                            prop["value"]["name"],
                            init_obj.get(traverser, prop_name))
                    elif prop["value"]["type"] == "ObjectPattern":
                        _proc_objpattern(init_obj.get(traverser, prop_name),
                                         prop["value"]["properties"])

            if init is not None:
                _proc_objpattern(init_obj=init,
                                 properties=declaration["id"]["properties"])

        else:
            var_name = declaration["id"]["name"]
            traverser._debug("NAME>>%s" % var_name)

            var_value = traverser._traverse_node(declaration["init"])
            traverser._debug("VALUE>>%s" % (var_value.output()
                                            if var_value is not None
                                            else "None"))

            if not isinstance(var_value, JSWrapper):
                var = JSWrapper(value=var_value,
                                const=kind == "const",
                                traverser=traverser)
            else:
                var = var_value
                var.const = kind == "const"

            traverser._declare_variable(var_name, var, type_=kind)

    if "body" in node:
        traverser._traverse_node(node["body"])

    traverser.debug_level -= 1

    # The "Declarations" branch contains custom elements.
    return True
コード例 #32
0
def _define_var(traverser, node):
    'Creates a local context variable'

    traverser._debug('VARIABLE_DECLARATION')
    traverser.debug_level += 1

    declarations = (node['declarations']
                    if 'declarations' in node else node['head'])

    kind = node.get('kind', 'let')
    for declaration in declarations:

        # It could be deconstruction of variables :(
        if declaration['id']['type'] == 'ArrayPattern':

            vars = []
            for element in declaration['id']['elements']:
                # NOTE : Multi-level array destructuring sucks. Maybe implement
                # it someday if you're bored, but it's so rarely used and it's
                # so utterly complex, there's probably no need to ever code it
                # up.
                if element is None or element['type'] != 'Identifier':
                    vars.append(None)
                    continue
                vars.append(element['name'])

            # The variables are not initialized
            if declaration['init'] is None:
                # Simple instantiation; no initialization
                for var in vars:
                    if not var:
                        continue
                    traverser._declare_variable(var, None)

            # The variables are declared inline
            elif declaration['init']['type'] == 'ArrayPattern':
                # TODO : Test to make sure len(values) == len(vars)
                for value in declaration['init']['elements']:
                    if vars[0]:
                        traverser._declare_variable(
                            vars[0],
                            JSWrapper(traverser._traverse_node(value),
                                      traverser=traverser))
                    vars = vars[1:]  # Pop off the first value

            # It's being assigned by a JSArray (presumably)
            elif declaration['init']['type'] == 'ArrayExpression':

                assigner = traverser._traverse_node(declaration['init'])
                for value in assigner.value.elements:
                    if vars[0]:
                        traverser._declare_variable(vars[0], value)
                    vars = vars[1:]

        elif declaration['id']['type'] == 'ObjectPattern':

            init = traverser._traverse_node(declaration['init'])

            def _proc_objpattern(init_obj, properties):
                for prop in properties:
                    # Get the name of the init obj's member
                    if prop['key']['type'] == 'Literal':
                        prop_name = prop['key']['value']
                    elif prop['key']['type'] == 'Identifier':
                        prop_name = prop['key']['name']
                    else:
                        continue

                    if prop['value']['type'] == 'Identifier':
                        traverser._declare_variable(
                            prop['value']['name'],
                            init_obj.get(traverser, prop_name))
                    elif prop['value']['type'] == 'ObjectPattern':
                        _proc_objpattern(init_obj.get(traverser, prop_name),
                                         prop['value']['properties'])

            if init is not None:
                _proc_objpattern(init_obj=init,
                                 properties=declaration['id']['properties'])

        else:
            var_name = declaration['id']['name']
            traverser._debug('NAME>>%s' % var_name)

            var_value = traverser._traverse_node(declaration['init'])
            traverser._debug(
                'VALUE>>%s' %
                (var_value.output() if var_value is not None else 'None'))

            if not isinstance(var_value, JSWrapper):
                var = JSWrapper(value=var_value,
                                const=kind == 'const',
                                traverser=traverser)
            else:
                var = var_value
                var.const = kind == 'const'

            traverser._declare_variable(var_name, var, type_=kind)

    if 'body' in node:
        traverser._traverse_node(node['body'])

    traverser.debug_level -= 1

    # The "Declarations" branch contains custom elements.
    return True
コード例 #33
0
def boolean_global(wrapper, arguments, traverser):
    if not arguments:
        return JSWrapper(False, traverser=traverser)
    arg = traverser._traverse_node(arguments[0])
    return JSWrapper(bool(arg.get_literal_value()), traverser=traverser)
コード例 #34
0
FUNCTION_EXPORT_HELP = (
    'Given the potential security risks of exposing APIs to unprivileged '
    'code, extensions which use these APIs must undergo manual review for at '
    'least one submission. If you are not using these APIs to interact with '
    'content code, please consider alternatives, such as built-in '
    'message passing functionality.')

# GLOBAL_ENTITIES is also representative of the `window` object.
GLOBAL_ENTITIES = {
    u'window': {
        'value': lambda t: {
            'value': GLOBAL_ENTITIES
        }
    },
    u'null': {
        'literal': lambda t: JSWrapper(None, traverser=t)
    },
    u'Cc': {
        'readonly': False,
        'value': lambda t: GLOBAL_ENTITIES['Components']['value']['classes']
    },
    u'Ci': {
        'readonly': False,
        'value': lambda t: GLOBAL_ENTITIES['Components']['value']['interfaces']
    },
    u'Cu': {
        'readonly': False,
        'value': lambda t: GLOBAL_ENTITIES['Components']['value']['utils']
    },

    # From Services.jsm.
コード例 #35
0
 def wrap(t):
     return JSWrapper(value, traverser=t)