-
Notifications
You must be signed in to change notification settings - Fork 15.6k
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
[ruby] Unable to instantiate a descriptor in v3.24.0 on 32-bit system #13481
Comments
This diff appears to fix the issue: diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index c9354db4e..c575ffe4f 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -279,14 +279,14 @@ static void ObjectCache_Init(VALUE protobuf) {
VALUE ObjectCache_TryAdd(const void *key, VALUE val) {
VALUE key_val = (VALUE)key;
PBRUBY_ASSERT((key_val & 3) == 0);
- return rb_funcall(weak_obj_cache, item_try_add, 2, LL2NUM(key_val), val);
+ return rb_funcall(weak_obj_cache, item_try_add, 2, LL2NUM(key_val >> 2), val);
}
// Returns the cached object for this key, if any. Otherwise returns Qnil.
VALUE ObjectCache_Get(const void *key) {
VALUE key_val = (VALUE)key;
PBRUBY_ASSERT((key_val & 3) == 0);
- return rb_funcall(weak_obj_cache, item_get, 1, LL2NUM(key_val));
+ return rb_funcall(weak_obj_cache, item_get, 1, LL2NUM(key_val >> 2));
}
/* This restores the previous behavior of |
protocolbuffers#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, it appears that `LL2NUM(key_val)` returns inconsistent results, possibly due to overflow. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. Closes protocolbuffers#13481
protocolbuffers#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, LL2NUM(key_val) returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. Closes protocolbuffers#13481
I realize after updating #13494 that this problem may also show up on a 64-bit system if the |
protocolbuffers#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign bit. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes protocolbuffers#13481
#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign flag. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes #13481 Closes #13494 COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a FUTURE_COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a PiperOrigin-RevId: 557189479
#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign flag. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes #13481 Closes #13494 COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a FUTURE_COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a PiperOrigin-RevId: 557189479
#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign flag. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes #13481 Closes #13494 COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a FUTURE_COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a PiperOrigin-RevId: 557216800
I merged the proposed changes. Thank you @stanhu for including the new test config as well! |
#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign flag. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes #13481 Closes #13494 COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a PiperOrigin-RevId: 557211768
#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign flag. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes #13481 Closes #13494 COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a PiperOrigin-RevId: 557211768
#13204 refactored the Ruby object cache to use a key of `LL2NUM(key_val)` instead of `LL2NUM(key_val >> 2)`. On 32-bit systems, `LL2NUM(key_val)` returns inconsistent results because a large value has to be stored as a Bignum on the heap. This causes cache lookups to fail. This commit restores the previous behavior of using `ObjectCache_GetKey`, which discards the lower 2 bits, which are zero. This enables a key to be stored as a Fixnum on both 32 and 64-bit platforms. As https://patshaughnessy.net/2014/1/9/how-big-is-a-bignum describes, a Fixnum uses: * 1 bit for the `FIXNUM_FLAG`. * 1 bit for the sign flag. Therefore the largest possible Fixnum value on a 64-bit value is 4611686018427387903 (2^62 - 1). On a 32-bit system, the largest value is 1073741823 (2^30 - 1). For example, a possible VALUE pointer address on a 32-bit system: 0xff5b4af8 => 4284173048 Dropping the lower 2 bits makes up for the loss of range to these flags. In the example above, we see that shifting by 2 turns the value into a 30-bit number, which can be represented as a Fixnum: (0xff5b4af8 >> 2) => 1071043262 This bug can also manifest on a 64-bit system if the upper bits are 0xff. Closes #13481 Closes #13494 COPYBARA_INTEGRATE_REVIEW=#13494 from stanhu:sh-fix-ruby-protobuf-32bit d63122a PiperOrigin-RevId: 557211768 Co-authored-by: Stan Hu <stanhu@gmail.com>
What version of protobuf and what language are you using?
Version: v3.24.0
Language: Ruby
What operating system (Linux, Windows, ...) and version?
Linux on a Raspberry Pi 2 Debian image (armv6l)
What runtime / compiler are you using (e.g., python version or gcc version)
Ruby 3.0.5
What did you do?
Steps to reproduce the behavior:
docker run -it registry.gitlab.com/gitlab-org/gitlab-omnibus-builder/rpi_10:4.20.0 bash gem install pg_query ruby -r pg_query -e "puts 'done'"
What did you expect to see
The library loads without error with
done
. This works fine on v3.23.0.What did you see instead?
This might just be an emulation issue, but I'm seeing this strange behavior when trying to debug this:
@fowles @casperisfine I think this is related to the object cache refactoring in #13204. Wondering if there is a pointer size issue here.
The text was updated successfully, but these errors were encountered: