-
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rework HashMap internals and add RNG support
The internals of HashMap, and in particular the hashing logic, were broken. Internally the VM reused Rust's DefaultHasher type for hashing values. This type is mutable. When storing a HashMap in a constant, concurrent access to this HashMap could result in wrong hashes being produced, as all threads use the same DefaultHasher. To solve this, Inko takes a similar approach as Rust: we provide a RandomState type, which can be used to create a DefaultHasher. A DefaultHasher now takes two keys as arguments, used for seeding the hasher. The RandomState type generates two keys randomly, similar to Rust. The hash seeds are generated by taking a thread-local randomly generated number, then incrementing it (wrapping around on overflow). This ensures that it is very unlikely for two different HashMaps to use the same seeds, making certain hash attacks [1] more difficult. Random number generation is provided by the std::random module. This module provides methods for randomly generating integers, floats, and bytes. Integers and floats can also be generated in a given range, for example: import std::random random.integer_between(min: 0, max: 10) [1]: rust-lang/rust#36481 and https://internals.rust-lang.org/t/help-harden-hashmap-in-libstd/4138/18
- Loading branch information
Yorick Peterse
committed
Jun 16, 2019
1 parent
23f2e7f
commit 770bc94
Showing
28 changed files
with
846 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#! Generating of random values. | ||
#! | ||
#! This module provides methods for generating random numbers and bytes. | ||
import std::byte_array::ByteArray | ||
import std::conversion::(ToFloat, ToInteger) | ||
|
||
## Returns a random `Integer`. | ||
def integer -> Integer { | ||
_INKOC.random_number(0) as Integer | ||
} | ||
|
||
## Returns a random `Integer` that is incremented on every request. | ||
## | ||
## The base number is a OS thread-specific randomly generated number. This | ||
## number is incremented upon calling this method. The number will wrap around | ||
## when it can not fit in a 64 bits unsigned integer. | ||
## | ||
## Since the base values are thread-specific, the values of this method may | ||
## differ depending on what OS thread the current process is running on. | ||
## | ||
## # Examples | ||
## | ||
## Requesting an incremental random `Integer`: | ||
## | ||
## import std::random | ||
## | ||
## let one = random.incremental_integer | ||
## let two = random.incremental_integer | ||
## | ||
## two - one # => 1 | ||
def incremental_integer -> Integer { | ||
_INKOC.random_number(1) as Integer | ||
} | ||
|
||
## Returns a random `Float`. | ||
def float -> Float { | ||
_INKOC.random_number(2) as Float | ||
} | ||
|
||
## Returns a random `Integer` in the given range. | ||
## | ||
## The returned `Integer` is greater than or equal to `min`, and lower than or | ||
## equal to `max`. | ||
## | ||
## # Panics | ||
## | ||
## This method will panic if `min` is equal to or greater than `max`. | ||
def integer_between(min: ToInteger, max: ToInteger) -> Integer { | ||
_INKOC.random_range(min.to_integer, max.to_integer) as Integer | ||
} | ||
|
||
## Returns a random `Float` in the given range. | ||
## | ||
## The returned `Float` is greater than or equal to `min`, and lower than or | ||
## equal to `max`. | ||
## | ||
## # Panics | ||
## | ||
## This method will panic if `min` is equal to or greater than `max`. | ||
def float_between(min: ToFloat, max: ToFloat) -> Float { | ||
_INKOC.random_range(min.to_float, max.to_float) as Float | ||
} | ||
|
||
## Returns a `ByteArray` containing random bytes. | ||
## | ||
## The returned `ByteArray` will contain exactly `size` bytes. | ||
## | ||
## # Panics | ||
## | ||
## This method might panic if no random bytes could be generated. | ||
def bytes(size: Integer) -> ByteArray { | ||
_INKOC.random_bytes(size) | ||
} |
Oops, something went wrong.