ctutils: `CtLookup` index counter overflows. A 256-entry table with a `u8` index panics on every lookup with overflow checks on, and longer tables return the wrong element in release
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 59/100
Hướng nghiên cứu
Read src/traits/ct_lookup.rs:28-38 and inspect the CtLookup tests to understand the counter’s bounds and existing behavior. Reproduce both cases with a 256-entry and a 300-entry table using a u8 index. Done means full-size tables do not panic with overflow checks enabled and oversized tables cannot silently return a later element.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Body
ctutils 0.4.8, src/traits/ct_lookup.rs:28-38:
let mut i = Idx::default();
for item in self {
ret.insert_if(item, i.ct_eq(&index));
// TODO(tarcieri): ideally we'd prevent overflow here but there's no core `CheckedAdd`
i += Idx::from(1u8);
}
The TODO already notes that the counter can overflow. This issue is about two
concrete consequences, including one for the most natural use of the API:
- Panic on every lookup for an exactly-full table. A 256-entry table with
au8index (an AES-style S-box) incrementsipastu8::MAXafter
the last element. With overflow checks enabled (debug builds, or release
profiles withoverflow-checks = true), every call toct_lookuppanics
withattempt to add with overflowatct_lookup.rs:36, even though every
u8index is valid for that table. - Wrong element for longer tables in default release. For a table longer
than the index type can address (e.g. 300 entries,u8index),iwraps
and later entries overwrite the correct match.ct_lookup(0u8)returns
element 256, andct_lookup(5u8)returns element 261.
Reproduction
Cargo.toml:
[package]
name = "ct-lookup-overflow"
version = "0.1.0"
edition = "2021"
[dependencies]
ctutils = "=0.4.8"
src/main.rs:
#![forbid(unsafe_code)]
use ctutils::CtLookup;
fn main() {
// (1) 256-entry table, u8 index
let sbox: [u8; 256] = core::array::from_fn(|i| (i as u8).wrapping_mul(7) ^ 0x63);
println!("sbox[0x42] = {:?}", sbox.ct_lookup(0x42u8).into_option());
// (2) 300-entry table, u8 index
let table: Vec<u32> = (0..300u32).map(|i| 1000 + i).collect();
for idx in [0u8, 5, 43, 44, 255] {
println!("ct_lookup({idx}) = {:?}, expected {:?}",
table.as_slice().ct_lookup(idx).into_option(), table.get(idx as usize));
}
}
Output with rustc 1.99.1:
$ cargo run # debug (overflow checks on)
thread 'main' panicked at .../ctutils-0.4.8/src/traits/ct_lookup.rs:36:13:
attempt to add with overflow
$ cargo run --release # overflow checks off
sbox[0x42] = Some(173)
ct_lookup(0) = Some(1256), expected Some(1000)
ct_lookup(5) = Some(1261), expected Some(1005)
ct_lookup(43) = Some(1299), expected Some(1043)
ct_lookup(44) = Some(1044), expected Some(1044)
ct_lookup(255) = Some(1255), expected Some(1255)
Affects every release containing CtLookup (checked: 0.3.2 and 0.4.0 through
0.4.8). Master is unchanged.
Possible fixes
Any of the following:
- Skip the increment after the last element (e.g. increment at the top of
each iteration except the first). That makes exactly-full tables such as a
256-entryu8-indexed S-box work under overflow checks. - Reject tables longer than the index type can address, with a length check
(public information, so not a constant-time concern) or a documented
debug_assert!, so that wrapping can't silently select the wrong element. - Track the position as
usizeand convert the index once, if theIdx
bounds allow it.
- Ngôn ngữ chính
- Rust
- Star
- 688
- Fork
- 177
- Merge trung bình
- 2 giờ 31 phút
- Pull request đã merge (30 ngày)
- 31
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của RustCrypto/utils
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
RustCrypto/utils#1597 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
RustCrypto/utils#1555 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
RustCrypto/utils#1546 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
inout: improve test coverageĐang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
RustCrypto/utils#1562 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
RustCrypto/utils#1537 · 7 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của RustCrypto/utils
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Non-`main` default branchesĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
max-sixty/worktrunk#4727 · 7 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
Maintainer thường phản hồi trong vòng 1 ngày
-
follow-up
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
carrick-sh/carrick#1859 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
crate: spate-kafka documentation priority: medium
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 1 ngày