fix reserve ocaml block pointer arithmetic
commit49a9da920416e301030f3be98fe94fe0098402a5
authorSteve Cao <shiqicao@fb.com>
Thu, 5 Dec 2019 23:28:04 +0000 (5 15:28 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 5 Dec 2019 23:30:50 +0000 (5 15:30 -0800)
treebf8e36de44cc71fac7648fd24170d167ba390d85
parent8b5573162dbd84c502612a0cd5c71b8633d05e24
fix reserve ocaml block pointer arithmetic

Summary:
hackc crashed for www/flib/autoload/autoload_map.php, which contains a very large string(~400M).

The root cause is Rust treats pointer as usize, but the pointer arithmetic logic in reserve_block assumes pointer as isize.

Detail,

A ocaml mem chunk is represented by three pointers,
- ocamlpool_bound
- ocamlpool_limit
- ocamlpool_cursor

ocamlpool_bound is the base pointer address of a chunk whereas ocamlpool_limit is the top of a chunk, ocamlpool_cursor points to first free address within the chunk. The allocation grows from higher address number to lower address number. For example,

- ocamlpool_bound == 0x10
- ocamlpool_limit == 0x02
- ocamlpool_cursor == 0x08

`reserve_block(size)` requests `size` number of words, it calculates the new block pointer, `ocamlpool_cursor - size`, then checks whether it is greater than `ocamlpool_limit`, if true, then just return the pointer, if false, it needs to reserve another chunk.

In `ocamlpool_cursor - size`, if `size > ocamlpool_curosr` the result is negative value, *however*, pointer comparison in Rust is treated as comparison of two `usize` numbers, a negative value is always greater than `ocamlpool_limit`. A check with `ocamlpool_bound` is added to avoid segmentation fault.

Reviewed By: dabek

Differential Revision: D18830168

fbshipit-source-id: e9d466649b2fd2effb7eba0dd0817ced89f724d7
hphp/hack/src/utils/ocamlpool_rust/utils.rs