Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleaner contracts #10

Open
SolalPirelli opened this issue Nov 2, 2022 · 0 comments
Open

Cleaner contracts #10

SolalPirelli opened this issue Nov 2, 2022 · 0 comments

Comments

@SolalPirelli
Copy link
Member

SolalPirelli commented Nov 2, 2022

@tharvik this is a quick example of what I meant in our discussion yesterday as what index_pool's contract could look like instead of the current angr-dependent mess:

from klint import assume, any_bool, any_int, Map, sizeof
from klint.types import size_t, time_t, TIME_MAX, SIZE_MAX

# ideally we'd be able to use "not", "and", "or" but that requires patching the Python interpreter so... probably not
# instead, ~, &, | it is...

# I wonder if those doc comments are even needed? perhaps only optionally for the names of the function
# if they don't follow some convention (like struct_name_method_name), the parameters can probably be inferred?

class IndexPool:
    def __init__(self, size, expiration_time):
        """struct index_pool* index_pool_alloc(size_t size, time_t expiration_time)"""
        assert(size * sizeof(time_t) <= SIZE_MAX)
        self.size = size
        self.expiration_time = expiration_time
        self.items = Map(size_t, time_t)

    def borrow(self, time):
        """bool index_pool_borrow(struct index_pool* pool, time_t time, size_t* out_index, bool* out_used)"""
        assert(time != TIME_MAX)
        result = any_bool()
        index = any_int()
        used = any_bool()
        if self.items.length() == self.size:
            if self.items.forall(lambda k, v: time < self.expiration_time | (time - self.expiration_time) <= v):
                assume(~result)
            else:
                assume(result)
                assume(used)
        else:
             assume(result)
        if result:
            assume(index < self.size)
            if used:
                assume(self.items.contains(index))
                assume(time >= self.expiration_time)
                assume((time - self.expiration_time) > self.items.get(index))
            else:
                assume(~self.items.contains(index))
            self.items.set(index, time)
        return (result, index, used)

    def refresh(self, time, index):
        """void index_pool_refresh(struct index_pool* pool, time_t time, size_t index)"""
        assert(time != TIME_MAX)
        assert(index < self.size)
        self.items.set(index, time)

    def used(self, time, index):
        """"bool index_pool_used(struct index_pool* pool, time_t time, size_t index)"""
        value = self.items.get(index)
        if value is None:
            return False
        else:
            return time < self.expiration_time | (time - self.expiration_time) <= value

    def return(self, index):
        """void index_pool_return(struct index_pool* pool, size_t index)"""
        assert(index < self.size)
        self.items.remove(index)

Obviously just an example, I'm not even 100% sure it has all of the info necessary and only that, but I thought it'd be useful to write a clean version since the angr-specific one is a bit of a pain to understand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant