summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGvozden Neskovic <[email protected]>2016-09-02 15:10:34 +0200
committerBrian Behlendorf <[email protected]>2016-09-29 15:55:41 -0700
commit6ca636a1526ea08a7e0a972fa164b22815529d4b (patch)
tree59ffe0bd8cf66168cb941ff26ac92886e203e69d
parent4ca9c1de129f8250c446c2355349e6b300d84586 (diff)
Avoid undefined shift overflow in fzap_cursor_retrieve()
Avoid calculating (1<<64) if lh_prefix_len == 0. Semantics of the method remain the same. Assert (lh_prefix_len > 0) in zap_expand_leaf() to detect possibly the same problem. Issue #4883 Signed-off-by: Gvozden Neskovic <[email protected]>
-rw-r--r--module/zfs/zap.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/module/zfs/zap.c b/module/zfs/zap.c
index 0ed6d7f49..a8ccd2895 100644
--- a/module/zfs/zap.c
+++ b/module/zfs/zap.c
@@ -693,6 +693,8 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l,
ASSERT0(err); /* we checked for i/o errors above */
}
+ ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_prefix_len, >, 0);
+
if (hash & (1ULL << (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len))) {
/* we want the sibling */
zap_put_leaf(l);
@@ -1230,17 +1232,23 @@ again:
err = zap_leaf_lookup_closest(l, zc->zc_hash, zc->zc_cd, &zeh);
if (err == ENOENT) {
- uint64_t nocare =
- (1ULL << (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len)) - 1;
- zc->zc_hash = (zc->zc_hash & ~nocare) + nocare + 1;
- zc->zc_cd = 0;
- if (zap_leaf_phys(l)->l_hdr.lh_prefix_len == 0 ||
- zc->zc_hash == 0) {
+ if (zap_leaf_phys(l)->l_hdr.lh_prefix_len == 0) {
zc->zc_hash = -1ULL;
+ zc->zc_cd = 0;
} else {
- zap_put_leaf(zc->zc_leaf);
- zc->zc_leaf = NULL;
- goto again;
+ uint64_t nocare = (1ULL <<
+ (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len)) - 1;
+
+ zc->zc_hash = (zc->zc_hash & ~nocare) + nocare + 1;
+ zc->zc_cd = 0;
+
+ if (zc->zc_hash == 0) {
+ zc->zc_hash = -1ULL;
+ } else {
+ zap_put_leaf(zc->zc_leaf);
+ zc->zc_leaf = NULL;
+ goto again;
+ }
}
}