Beispiel #1
0
def string_substring(x, args):
    startIndex = createZ3ExpressionFromConstraint(args[0], {})
    endIndex = lenOfZ3(x)
    if len(args) == 2:
        endIndex = createZ3ExpressionFromConstraint(args[1], {})

    return z3.SubString(x, startIndex, endIndex)
Beispiel #2
0
def string_split(x, args):
    st = x
    split_val = z3.StringVal(args[0].encode())
    x = transformNonBooleanLazyEvaluations(x)
    arr = z3.Array('__ignore_{}.split({})'.format(str(x), str(args[0])), z3.IntSort(), z3.StringSort())
    for i in range(3):
        index = z3.IndexOf(st, split_val, 0)
        s = z3.SubString(st, 0, index)
        st = z3.SubString(st, index + z3.Length(split_val), z3.Length(st))
        GLOBAL_CONSTRAINTS.append(z3.Select(arr, i) == s)
        GLOBAL_CONSTRAINTS.append(s != z3.StringVal(''))
        GLOBAL_ARRAY_HANDLER[arr].append(s)
    GLOBAL_CONSTRAINTS.append(z3.Select(arr, 3) == st)
    GLOBAL_CONSTRAINTS.append(st != z3.StringVal(''))
    GLOBAL_ARRAY_HANDLER[arr].append(st)
    # We just guess the length here and hope that this works for the program
    ARRAY_LENGTHS[str(arr.decl())] = 4

    GLOBAL_CONSTRAINTS.append(z3.IndexOf(GLOBAL_ARRAY_HANDLER[arr][-1], split_val, 0) == -1)
    # GLOBAL_CONSTRAINTS.append(z3.PrefixOf(GLOBAL_ARRAY_HANDLER[arr][0], x))

    return arr
Beispiel #3
0
def string_slice(x, args):
    if len(args) == 2:
        start = args[0]
        end = args[1]
    else:
        start = args[0]
        end = lenOfZ3(x)

    if type(start) != int:
        start = createZ3ExpressionFromConstraint(start, {})
    if type(end) != int and not z3.is_int(end):
        end = createZ3ExpressionFromConstraint(end, {})

    if type(start) == int and start < 0:
        GLOBAL_CONSTRAINTS.append(z3.Length(x) > -start)
        start = end + start

    if (z3.is_int(start) or type(start) == int) and (z3.is_int(start) or type(start) == int):
        return z3.SubString(x, start, end)
    else:
        raise NotSupportedException('')
Beispiel #4
0
def SSubstr(text: SStr, offset: SInt, length: SInt) -> z3.SeqRef:
    return z3.SubString(text.expr, offset.expr, length.expr)
Beispiel #5
0
def init(s: z3.SeqRef) -> z3.SeqRef:
    ctx = s.ctx
    zero = z3.IntVal(0, ctx)
    one = z3.IntVal(1, ctx)
    return z3.SubString(s, zero, z3.Length(s) - one)
Beispiel #6
0
def tail(s: z3.SeqRef) -> z3.SeqRef:
    ctx = s.ctx
    one = z3.IntVal(1, ctx)
    return z3.SubString(s, one, z3.Length(s))
def _internal_match_patterns(space: StateSpace, top_patterns: Any, flags: int,
                             smtstr: z3.ExprRef,
                             offset: int) -> Optional[_Match]:
    """
    >>> from crosshair.statespace import SimpleStateSpace
    >>> import sre_parse
    >>> smtstr = z3.String('smtstr')
    >>> space = SimpleStateSpace()
    >>> space.add(smtstr == z3.StringVal('aabb'))
    >>> _internal_match_patterns(space, sre_parse.parse('a+'), 0, smtstr, 0).span()
    (0, 2)
    >>> _internal_match_patterns(space, sre_parse.parse('ab'), 0, smtstr, 1).span()
    (1, 3)
    """
    matchstr = z3.SubString(smtstr, offset,
                            z3.Length(smtstr)) if offset > 0 else smtstr
    if len(top_patterns) == 0:
        return _Match([(None, offset, offset)])
    pattern = top_patterns[0]

    def continue_matching(prefix):
        suffix = _internal_match_patterns(space, top_patterns[1:], flags,
                                          smtstr, prefix.end())
        if suffix is None:
            return None
        return prefix._add_match(suffix)

    # TODO: using a typed internal function triggers __hash__es inside the typing module.
    # Seems like this casues nondeterminism due to a global LRU cache used by the typing module.
    def fork_on(expr, sz):
        if space.smt_fork(expr):
            return continue_matching(_Match([(None, offset, offset + sz)]))
        else:
            return None

    # Handle simple single-character expressions using z3's built-in capabilities.
    z3_re = single_char_regex(pattern, flags)
    if z3_re is not None:
        ch = z3.SubString(matchstr, 0, 1)
        return fork_on(z3.InRe(ch, z3_re), 1)

    (op, arg) = pattern
    if op is MAX_REPEAT:
        (min_repeat, max_repeat, subpattern) = arg
        if max_repeat < min_repeat:
            return None
        reps = 0
        overall_match = _Match([(None, offset, offset)])
        while reps < min_repeat:
            submatch = _internal_match_patterns(space, subpattern, flags,
                                                smtstr, overall_match.end())
            if submatch is None:
                return None
            overall_match = overall_match._add_match(submatch)
            reps += 1
        if max_repeat != MAXREPEAT and reps >= max_repeat:
            return continue_matching(overall_match)
        submatch = _internal_match_patterns(space, subpattern, flags, smtstr,
                                            overall_match.end())
        if submatch is None:
            return continue_matching(overall_match)
        # we matched; try to be greedy first, and fall back to `submatch` as the last consumed match
        greedy_remainder = _patt_replace(
            top_patterns,
            arg,
            (
                1,
                max_repeat if max_repeat == MAXREPEAT else max_repeat -
                (min_repeat + 1),
                subpattern,
            ),
        )
        greedy_match = _internal_match_patterns(space, greedy_remainder, flags,
                                                smtstr, submatch.end())
        if greedy_match is not None:
            return overall_match._add_match(submatch)._add_match(greedy_match)
        else:
            match_with_optional = continue_matching(
                overall_match._add_match(submatch))
            if match_with_optional is not None:
                return match_with_optional
            else:
                return continue_matching(overall_match)
    elif op is BRANCH and arg[0] is None:
        # NOTE: order matters - earlier branches are more greedily matched than later branches.
        branches = arg[1]
        first_path = list(branches[0]) + list(top_patterns)[1:]
        submatch = _internal_match_patterns(space, first_path, flags, smtstr,
                                            offset)
        # _patt_replace(top_patterns, pattern, branches[0])
        if submatch is not None:
            return submatch
        if len(branches) <= 1:
            return None
        else:
            return _internal_match_patterns(
                space,
                _patt_replace(top_patterns, branches, branches[1:]),
                flags,
                smtstr,
                offset,
            )
    elif op is AT:
        if arg in (AT_END, AT_END_STRING):
            if arg is AT_END and re.MULTILINE & flags:
                raise ReUnhandled("Multiline match with AT_END_STRING")
            return fork_on(matchstr == z3.StringVal(""), 0)
    elif op is SUBPATTERN:
        (groupnum, _a, _b, subpatterns) = arg
        if (_a, _b) != (0, 0):
            raise ReUnhandled("unsupported subpattern args")
        new_top = (list(subpatterns) + [(_END_GROUP_MARKER,
                                         (groupnum, offset))] +
                   list(top_patterns)[1:])
        return _internal_match_patterns(space, new_top, flags, smtstr, offset)
    elif op is _END_GROUP_MARKER:
        (group_num, begin) = arg
        match = continue_matching(_Match([(None, offset, offset)]))
        if match is None:
            return None
        while len(match._groups) <= group_num:
            match._groups.append(None)
        match._groups[group_num] = (None, begin, offset)
        return match
    raise ReUnhandled(op)
def _slice_match_area(string, pos=0, endpos=None):
    smtstr = string.var
    if endpos is not None:
        smtstr = z3.SubString(smtstr, 0, endpos)
    return smtstr
Beispiel #9
0
def _slice_tail(string: SymbolicStr, endpos: Optional[int] = None) -> SymbolicStr:
    smtstr = string.var
    if endpos is not None:
        smtstr = z3.SubString(smtstr, 0, endpos)
    return smtstr