Ejemplo n.º 1
0
def trim_start(s: z3.SeqRef) -> z3.SeqRef:
    ctx = s.ctx

    trim_start = z3.RecFunction('trim_start', z3.StringSort(ctx), \
                                z3.StringSort(ctx))
    z3.RecAddDefinition(trim_start, s, \
        z3.If(is_whitespace(head(s)), \
              trim_start(tail(s)),
              s))

    return trim_start(s)
Ejemplo n.º 2
0
def to_case(name: str, name_char: Callable[[z3.Context], z3.FuncDeclRef], \
            text: z3.SeqRef) -> z3.SeqRef:
    ctx = text.ctx
    empty = z3.StringVal("", ctx)

    f = z3.RecFunction(name, z3.StringSort(ctx), z3.StringSort(ctx))
    z3.RecAddDefinition(f, text, \
        z3.If(text == empty, \
              empty,
              z3.Concat(name_char(ctx)(head(text)), \
                        f(tail(text)))))

    return f(text)
Ejemplo n.º 3
0
def case_char(name: str, map_: Dict[str, str], ctx: z3.Context) \
    -> z3.FuncDeclRef:
    char = z3.FreshConst(z3.StringSort(ctx))

    const = char
    for x, y in map_:
        const = z3.If(char == z3.StringVal(x, ctx), \
                      z3.StringVal(y, ctx),
                      const, ctx)

    f = z3.RecFunction(f'{name}_char', z3.StringSort(ctx), z3.StringSort(ctx))
    z3.RecAddDefinition(f, char, const)

    return f
Ejemplo n.º 4
0
def getTypedZ3ValFromIdentifier(identifier, types):
    if type(identifier) == dict:
        # FIXME how can we handle this here
        raise NotSupportedException('Complex objects as base for operations cannot be modelled in z3')
    if type(identifier) == list:
        arr = z3.Array('ignore_helper_constant_array_' + randomString(), z3.IntSort(), z3.StringSort())
        for i, arg in enumerate(identifier):
            GLOBAL_CONSTRAINTS.append(z3.Select(arr, i) == createZ3ExpressionFromConstraint(arg, types))
        ARRAY_LENGTHS[str(arr.decl())] = len(identifier)
        return arr

    cur_types = types
    GLOBAL_IDENTIFIER.add(identifier)
    cur_types = infered_types[identifier]
    # if cur_types == 'object':
    #    infered_types[identifier] = ''
    #    cur_types = ''
    if identifier.endswith('.length'):
        return z3.Length(z3.String(identifier[:-7]))

    if cur_types == 'string':
        return z3.String(identifier)
    elif cur_types == 'number':
        return z3.Int(identifier)
    elif cur_types == 'boolean':
        return z3.Bool(identifier)
    elif cur_types == 'array':
        return z3.Array(identifier, z3.IntSort(), z3.StringSort())

    if 'event.data' in identifier or 'event.origin' in identifier or 'event' == identifier:
        return z3.String(identifier)
    else:
        MAKE_UNSOLVABLE.add(identifier)
        return z3.String(identifier)
Ejemplo n.º 5
0
def type2sort(typ, ctx):
    if typ == int:
        return z3.IntSort(ctx)
    elif typ == str:
        return z3.StringSort(ctx)
    else:
        raise ValueError(f'Unsupported type: {typ}')
Ejemplo n.º 6
0
def SReplace(text: SStr, old: SStr, new: SStr) -> z3.SeqRef:
    ctx = text.ctx

    text, old, new = text.expr, old.expr, new.expr
    empty = z3.StringVal("", ctx)

    replace_all = z3.RecFunction('replace_all', \
        z3.StringSort(ctx), z3.StringSort(ctx), z3.StringSort(ctx), # from
        z3.StringSort(ctx))                                         # to

    z3.RecAddDefinition(replace_all, [text, old, new], \
        z3.If(z3.Or(old == empty, \
                    z3.Not(z3.Contains(text, old)), ctx),\
              text,
              replace_all(z3.Replace(text, old, new), \
                          old,
                          new)))

    return replace_all(text, old, new)
Ejemplo n.º 7
0
def sorts(name):
    if name.startswith('bv[') and name.endswith(']'):
        width = int(name[3:-1])
        return z3.BitVecSort(width)
    if name.startswith('strbv[') and name.endswith(']'):
        width = int(name[6:-1])
        return z3.BitVecSort(width)
    if name == 'int':
        return z3.IntSort()
    if name == 'strlit':
        return z3.StringSort()
    return None
Ejemplo n.º 8
0
    def _z3_sort(self, json_type, typeargs=[], typeargnames={}):
        # print "Looking up type %s (%s, %s): %s" % (json_type['name'], typeargs, typeargnames, json_type)

        ## Hard-coded Z3 correspondence for some types
        if json_type['name'] == 'nat':
            return z3.IntSort()

        if json_type['name'] == 'string':
            return z3.StringSort()

        if json_type['name'] == 'gmap':
            return z3.ArraySort(self._z3_sort(json_type['args'][0]),
                                self._z3_sort(json_type['args'][1]))

        if json_type['what'] == 'type:var':
            t = typeargnames[json_type['name']]
            return self._z3_sort(t)

        if json_type['what'] == 'type:glob':
            if json_type['name'] == 'buf':
                return z3.SeqSort(z3.BitVecSort(8))

            return self.z3_sort(json_type['name'], [
                self._type_var_lookup(typeargnames, x)
                for x in json_type['args']
            ])

        if str(json_type) in self.json_to_sort:
            return self.json_to_sort[str(json_type)]

        if json_type['name'] == 'list':
            return z3.SeqSort(self._z3_sort(typeargs[0]))

        datatype = z3.Datatype(str(json_type['name']))
        typeargnames = {}
        for i in range(0, len(typeargs)):
            typeargname = json_type['argnames'][i]
            typeargnames[typeargname] = typeargs[i]
        for c in json_type['constructors']:
            cname = str(c['name'])
            datatype.declare(
                cname,
                *[(cname + '_%d' % idx, self._z3_sort(argtype, [],
                                                      typeargnames))
                  for (idx, argtype) in enumerate(c['argtypes'])])

        t = datatype.create()
        self.json_to_sort[str(json_type)] = t
        return t
Ejemplo n.º 9
0
def getZ3(tuple):
    if tuple[0] == CONCAT:
        return z3.Concat(list(map(getZ3, list(tuple[1:]))))
    elif tuple[0] == STAR:
        return z3.Star(getZ3(tuple[1]))
    elif tuple[0] == DOT:
        res = z3.Range(chr(32), chr(127))
        return res
    elif tuple[0] == CHAR:
        return z3.Re(tuple[1])
    elif tuple[0] == BAR:
        return z3.Union(list(map(getZ3, list(tuple[1:]))))
    elif tuple[0] == GROUP:
        return getZ3(tuple[2])
    elif tuple[0] == EMPTY:
        return z3.Empty(z3.ReSort(z3.StringSort()))
    raise NotSupportedException('not yet supported', tuple[0])
Ejemplo n.º 10
0
def test_expression():
    expr_string = "(= a true)"
    expr = Expression(expr_string)
    assert expr.expression == expr_string
    with pytest.raises(InvalidExpression,
                       message="expected InvalidExpression"):
        assert Expression("((= a true)")

    ctx = z3.Context()
    var = Expression.create_z3_var(ctx, int, 'var')
    assert var.sort() == z3.IntSort(ctx=ctx)
    assert str(var) == 'var'
    assert var.ctx == ctx
    assert var.ctx != z3.main_ctx
    assert Expression.create_z3_var(None, bool, 'var').sort() == z3.BoolSort()
    assert Expression.create_z3_var(None, str, 'var').sort() == z3.StringSort()
    assert Expression.create_z3_var(None, float, 'var').sort() == z3.RealSort()
    with pytest.raises(UnsupportedVariableType,
                       message="expected UnsupportedVariableType"):
        assert Expression.create_z3_var(None, list, 'var')
Ejemplo n.º 11
0
    def __init__(self,
                 regex: str,
                 unknown: z3.StringSort(),
                 word_choice_cutoff=10,
                 dot_charset=DEFAULT_DOT_CHARSET,
                 star_lengths: Iterable[int] = DEFAULT_STAR_LENGTHS,
                 symbolic=False):
        """
        Compiles Regex to Z3 String expressions

        :param dot_charset: Characters that the DOT metachar can match. This should be limited to
            valid URL characters, or can be set to a taint marker.

        """

        self.unknown = unknown
        self.star_lengths = star_lengths

        self.string_var_count = 0
        self.bool_var_count = 0

        self.symbolic = symbolic

        _parser = parsing.RegexParser()
        parse_result = _parser.parse(regex)
        self.parsing_errors = parse_result['errors']
        regex_0 = flatten_regex(parse_result['root'])
        regex_1 = remove_path(regex_0)
        regex_2 = convert_stars(regex_1, star_lengths)
        regex_3 = convert_bars(regex_2, cutoff=word_choice_cutoff)
        if symbolic:
            regex_4, self.symbols = convert_to_encoded_symbols(regex_3, {})
        else:
            regex_4, self.symbols = regex_3, {}
        self.regex = regex_4
        assert self.regex
        self.groups = parse_result['groups']
        self.backrefs = parse_result['backrefs']
        self.dot_charset = dot_charset
Ejemplo n.º 12
0
    def setupProblem(self):
        self.stackvars = {}
        self.Qf = z3.Function("final", z3.SeqSort(z3.IntSort()), z3.BoolSort())
        self.d = z3.Function("delta", z3.SeqSort(z3.IntSort()),
                             z3.StringSort(), z3.SeqSort(z3.IntSort()))

        for (w, st, final, has_children) in self.t.iter():

            sv = b"stack" + base64.b16encode(w)
            self.stackvars[w] = Sequence(sv)

            self.s_add_finalstate(w, final)

            if final and has_children:
                self.s_add_nonemptystate(w)

            if len(w):
                self.s_add_transition_to(w)

        self.s.add(self.stackvars[b''] == z3.Unit(z3.IntVal(0)))

        # most useful convention:
        # accept by drained stack, but don't read any more and fail then
        self.s.add(self.Qf(z3.Empty(z3.SeqSort(z3.IntSort()))) == True)
Ejemplo n.º 13
0
def reverse(s: z3.SeqRef) -> z3.SeqRef:
    ctx = s.ctx

    empty = z3.StringVal("", ctx)
    acc = z3.FreshConst(z3.StringSort(ctx), 'acc')

    tail_rev = z3.RecFunction('reverse', \
                              z3.StringSort(ctx), z3.StringSort(ctx), \
                              z3.StringSort(ctx))
    z3.RecAddDefinition(tail_rev, [s, acc], \
                        z3.If(s == empty, \
                              acc,
                              tail_rev(tail(s),
                                       z3.Concat(head(s), acc))))

    rev = z3.RecFunction('reverse', z3.StringSort(ctx), \
                         z3.StringSort(ctx))
    z3.RecAddDefinition(rev, s, tail_rev(s, empty))

    return rev(s)
Ejemplo n.º 14
0
# z3.set_param("smt.string_solver", "z3str3")

with open('NFS3API_2.json') as f:
    code = f.read()
    j = json.loads(code)

jc = json_eval.Context()
jc.load(j)

m = jc.get_module('Main')

stateType = m.get_type("state")

sym = json_sym.SymbolicJSON(jc)
sym.register_base_type("positive", lambda args: z3.IntSort())
sym.register_base_type("string", lambda args: z3.StringSort())

# XXX u0 is a u64? and u1 is a u32...
sym.register_base_type("u0", lambda args: z3.BitVecSort(64))
sym.register_base_type("u1", lambda args: z3.BitVecSort(32))
sym.register_base_type(
    "gmap", lambda args: z3.ArraySort(
        sym.z3_sort(args[0]),
        sym.z3_sort({
            'what': 'type:glob',
            'name': 'option',
            'args': [args[1]],
            'mod': m,
        })))
sym.register_base_type("buf", lambda args: z3.SeqSort(z3.BitVecSort(8)))
# sym.register_base_type("list", lambda args: z3.SeqSort(sym.z3_sort(args[0])))
Ejemplo n.º 15
0
def getZ3ValFromJSVal(val):
    if type(val) == str:
        return z3.StringVal(val)
    if type(val) == bool:
        return z3.BoolVal(val)
    if type(val) == int:
        return z3.IntVal(val)
    if type(val) == int:
        return z3.IntVal(val)
    if type(val) == list:
        arr = z3.Array('ignore_helper_constant_array_' + randomString(), z3.IntSort(), z3.StringSort())
        for i, arg in enumerate(val):
            GLOBAL_CONSTRAINTS.append(z3.Select(arr, i) == createZ3ExpressionFromConstraint(arg, {}))
        ARRAY_LENGTHS[str(arr.decl())] = len(val)
        return arr
    if type(val) == dict:
        raise NotSupportedException('Complex Objects as base for operations with proxy strings are not yet supported!')

    raise Exception('Could not transform Js val to Z3 Val' + repr(val))
Ejemplo n.º 16
0
Archivo: z3.py Proyecto: bdrodes/pysmt
    def __init__(self, environment, z3_ctx):
        DagWalker.__init__(self, environment)
        self.mgr = environment.formula_manager
        self._get_type = environment.stc.get_type
        self._back_memoization = {}
        self.ctx = z3_ctx

        # Back Conversion
        self._back_fun = {
            z3.Z3_OP_AND: lambda args, expr: self.mgr.And(args),
            z3.Z3_OP_OR: lambda args, expr: self.mgr.Or(args),
            z3.Z3_OP_MUL: lambda args, expr: self.mgr.Times(args),
            z3.Z3_OP_ADD: lambda args, expr: self.mgr.Plus(args),
            z3.Z3_OP_DIV: lambda args, expr: self.mgr.Div(args[0], args[1]),
            z3.Z3_OP_IFF: lambda args, expr: self.mgr.Iff(args[0], args[1]),
            z3.Z3_OP_XOR: lambda args, expr:  self.mgr.Xor(args[0], args[1]),
            z3.Z3_OP_FALSE: lambda args, expr: self.mgr.FALSE(),
            z3.Z3_OP_TRUE: lambda args, expr: self.mgr.TRUE(),
            z3.Z3_OP_GT: lambda args, expr: self.mgr.GT(args[0], args[1]),
            z3.Z3_OP_GE: lambda args, expr: self.mgr.GE(args[0], args[1]),
            z3.Z3_OP_LT: lambda args, expr: self.mgr.LT(args[0], args[1]),
            z3.Z3_OP_LE: lambda args, expr: self.mgr.LE(args[0], args[1]),
            z3.Z3_OP_SUB: lambda args, expr: self.mgr.Minus(args[0], args[1]),
            z3.Z3_OP_NOT: lambda args, expr: self.mgr.Not(args[0]),
            z3.Z3_OP_IMPLIES: lambda args, expr: self.mgr.Implies(args[0], args[1]),
            z3.Z3_OP_ITE: lambda args, expr: self.mgr.Ite(args[0], args[1], args[2]),
            z3.Z3_OP_TO_REAL: lambda args, expr: self.mgr.ToReal(args[0]),
            z3.Z3_OP_BAND : lambda args, expr: self.mgr.BVAnd(args[0], args[1]),
            z3.Z3_OP_BOR : lambda args, expr: self.mgr.BVOr(args[0], args[1]),
            z3.Z3_OP_BXOR : lambda args, expr: self.mgr.BVXor(args[0], args[1]),
            z3.Z3_OP_BNOT : lambda args, expr: self.mgr.BVNot(args[0]),
            z3.Z3_OP_BNEG : lambda args, expr: self.mgr.BVNeg(args[0]),
            z3.Z3_OP_CONCAT : lambda args, expr: self.mgr.BVConcat(args[0], args[1]),
            z3.Z3_OP_ULT : lambda args, expr: self.mgr.BVULT(args[0], args[1]),
            z3.Z3_OP_ULEQ : lambda args, expr: self.mgr.BVULE(args[0], args[1]),
            z3.Z3_OP_SLT : lambda args, expr: self.mgr.BVSLT(args[0], args[1]),
            z3.Z3_OP_SLEQ : lambda args, expr: self.mgr.BVSLE(args[0], args[1]),
            z3.Z3_OP_UGT : lambda args, expr: self.mgr.BVUGT(args[0], args[1]),
            z3.Z3_OP_UGEQ : lambda args, expr: self.mgr.BVUGE(args[0], args[1]),
            z3.Z3_OP_SGT : lambda args, expr: self.mgr.BVSGT(args[0], args[1]),
            z3.Z3_OP_SGEQ : lambda args, expr: self.mgr.BVSGE(args[0], args[1]),
            z3.Z3_OP_BADD : lambda args, expr: self.mgr.BVAdd(args[0], args[1]),
            z3.Z3_OP_BMUL : lambda args, expr: self.mgr.BVMul(args[0], args[1]),
            z3.Z3_OP_BUDIV : lambda args, expr: self.mgr.BVUDiv(args[0], args[1]),
            z3.Z3_OP_BSDIV : lambda args, expr: self.mgr.BVSDiv(args[0], args[1]),
            z3.Z3_OP_BUREM : lambda args, expr: self.mgr.BVURem(args[0], args[1]),
            z3.Z3_OP_BSREM : lambda args, expr: self.mgr.BVSRem(args[0], args[1]),
            z3.Z3_OP_BSHL : lambda args, expr: self.mgr.BVLShl(args[0], args[1]),
            z3.Z3_OP_BLSHR : lambda args, expr: self.mgr.BVLShr(args[0], args[1]),
            z3.Z3_OP_BASHR : lambda args, expr: self.mgr.BVAShr(args[0], args[1]),
            z3.Z3_OP_BSUB : lambda args, expr: self.mgr.BVSub(args[0], args[1]),
            z3.Z3_OP_EXT_ROTATE_LEFT : lambda args, expr: self.mgr.BVRol(args[0], args[1].bv_unsigned_value()),
            z3.Z3_OP_EXT_ROTATE_RIGHT: lambda args, expr: self.mgr.BVRor(args[0], args[1].bv_unsigned_value()),
            z3.Z3_OP_BV2INT: lambda args, expr: self.mgr.BVToNatural(args[0]),
            z3.Z3_OP_POWER : lambda args, expr: self.mgr.Pow(args[0], args[1]),
            z3.Z3_OP_SELECT : lambda args, expr: self.mgr.Select(args[0], args[1]),
            z3.Z3_OP_STORE : lambda args, expr: self.mgr.Store(args[0], args[1], args[2]),
            z3.Z3_OP_SEQ_LENGTH: lambda args, expr: self.mgr.StrLength(args[0]),
            z3.Z3_OP_SEQ_CONCAT: lambda args, expr: self.mgr.StrConcat(args),
            z3.Z3_OP_SEQ_AT: lambda args, expr: self.mgr.StrCharAt(args[0], args[1]),
            z3.Z3_OP_SEQ_CONTAINS: lambda args, expr: self.mgr.StrContains(args[0], args[1]),
            z3.Z3_OP_SEQ_INDEX: lambda args, expr: self.mgr.StrIndexOf(args[0], args[1], args[2]),
            z3.Z3_OP_SEQ_REPLACE: lambda args, expr: self.mgr.StrReplace(args[0], args[1], args[2]),
            z3.Z3_OP_SEQ_EXTRACT: lambda args, expr: self.mgr.StrSubstr(args[0], args[1], args[2]),
            z3.Z3_OP_SEQ_PREFIX: lambda args, expr: self.mgr.StrPrefixOf(args[0], args[1]),
            z3.Z3_OP_SEQ_SUFFIX: lambda args, expr: self.mgr.StrSuffixOf(args[0], args[1]),
            z3.Z3_OP_INT_TO_STR: lambda args, expr: self.mgr.IntToStr(args[0]),
            z3.Z3_OP_STR_TO_INT: lambda args, expr: self.mgr.StrToInt(args[0]),
            # Actually use both args, expr
            z3.Z3_OP_SIGN_EXT: lambda args, expr: self.mgr.BVSExt(args[0], z3.get_payload(expr, 0)),
            z3.Z3_OP_ZERO_EXT: lambda args, expr: self.mgr.BVZExt(args[0], z3.get_payload(expr, 0)),
            z3.Z3_OP_ROTATE_LEFT: lambda args, expr: self.mgr.BVRol(args[0], z3.get_payload(expr, 0)),
            z3.Z3_OP_ROTATE_RIGHT: lambda args, expr: self.mgr.BVRor(args[0], z3.get_payload(expr, 0)),
            z3.Z3_OP_EXTRACT: lambda args, expr: self.mgr.BVExtract(args[0],
                                                              z3.get_payload(expr, 1),
                                                              z3.get_payload(expr, 0)),
            # Complex Back Translation
            z3.Z3_OP_EQ : self._back_z3_eq,
            z3.Z3_OP_UMINUS : self._back_z3_uminus,
            z3.Z3_OP_CONST_ARRAY : self._back_z3_const_array,
        }
        # Unique reference to Sorts
        self.z3RealSort = z3.RealSort(self.ctx)
        self.z3BoolSort = z3.BoolSort(self.ctx)
        self.z3IntSort  = z3.IntSort(self.ctx)
        self.z3StrSort  = z3.StringSort(self.ctx)
        self._z3ArraySorts = {}
        self._z3BitVecSorts = {}
        self._z3Sorts = {}
        # Unique reference to Function Declaration
        self._z3_func_decl_cache = {}
        return
Ejemplo n.º 17
0
# Or can you? Because pure must be imported as * and names cannot be reassigned?
for (patt, repl, condition) in [
        # # ('F(reduce(R, L, I))', 'reduce(R`, map(F, L), I)', reduce_fn_check),
]:
    basic_simplifier.add(exprparse(patt), exprparse(repl), condition)

# expr = exprparse('IsTruthy(isint(c) and isint(d))')
# rewritten = basic_simplifier.rewrite(expr)
# print('rewrite engine test', unparse(expr), unparse(rewritten))

PyFunc = z3.DeclareSort('PyFunc')
Unk = z3.Datatype('Unk')
Unk.declare('none')
Unk.declare('bool', ('tobool', z3.BoolSort()))
Unk.declare('int', ('toint', z3.IntSort()))
Unk.declare('string', ('tostring', z3.StringSort()))
Unk.declare('func', ('tofunc', PyFunc))
Unk.declare('app', ('tl', Unk), ('hd', Unk))
Unk.declare('_')  # empty tuple
Unk.declare('undef')  # error value
(Unk, ) = z3.CreateDatatypes(Unk)
App = z3.Function('.', Unk, Unk, Unk)


class ZHolder():
    pass


Z = ZHolder()
Z.Wrapbool = Unk.bool
Z.Wrapint = Unk.int
Ejemplo n.º 18
0
 def make_string_sort(self):
     return z3.StringSort(self.ctx())
Ejemplo n.º 19
0
            return SymbolicSeq(self.z3var + other.z3var)
        else:
            return SymbolicSeq(self.z3var + other)

    def __eq__(self, other):
        if isinstance(other, SymbolicSeq):
            return z3.Eq(self.z3var, other.z3var)
        else:
            return NotImplemented


_TYPE_TO_SMT_SORT = {
    int: z3.IntSort(),
    float: z3.Float64(),
    bool: z3.BoolSort(),
    str: z3.StringSort(),
}


def type_to_smt_sort(t: Type):
    if t in _TYPE_TO_SMT_SORT:
        return _TYPE_TO_SMT_SORT[t]
    origin = getattr(t, '__origin__', None)
    if origin in (List, Sequence, Container):
        item_type = t.__args__[0]
        return z3.SeqSort(type_to_smt_sort(item_type))
    elif origin in (Dict, Mapping):
        key_type, val_type = t.__args__
        return z3.ArraySort(type_to_smt_sort(key_type),
                            type_to_smt_sort(val_type))
    return None
Ejemplo n.º 20
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