about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2014-11-06 15:10:24 -0800
committerSimon Sapin <simon.sapin@exyr.org>2014-11-06 18:15:59 -0800
commit1fdb7595278df6568cc73028a734ca7d0615e622 (patch)
tree16c21d4eb207e70541dc3cd69a8e585898f065fe
parent45cbdec4174778bf915f17561ef971c068a7fcbc (diff)
downloadrust-1fdb7595278df6568cc73028a734ca7d0615e622.tar.gz
rust-1fdb7595278df6568cc73028a734ca7d0615e622.zip
Make EnumSet not silently corrupt data.
Assert at run time instead. Fixes #13756.

I’d rather have this be detected at compile-time, but I don’t know how to do that.
-rw-r--r--src/libcollections/enum_set.rs31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index 77eee98ecd8..c2c56554f7c 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -52,7 +52,9 @@ pub trait CLike {
 }
 
 fn bit<E:CLike>(e: &E) -> uint {
-    1 << e.to_uint()
+    let value = e.to_uint();
+    assert!(value < ::core::uint::BITS);
+    1 << value
 }
 
 impl<E:CLike> EnumSet<E> {
@@ -378,4 +380,31 @@ mod test {
         let elems = e_subtract.iter().collect();
         assert_eq!(vec![A], elems)
     }
+
+    #[test]
+    #[should_fail]
+    fn test_overflow() {
+        #[allow(dead_code)]
+        #[repr(uint)]
+        enum Bar {
+            V00, V01, V02, V03, V04, V05, V06, V07, V08, V09,
+            V10, V11, V12, V13, V14, V15, V16, V17, V18, V19,
+            V20, V21, V22, V23, V24, V25, V26, V27, V28, V29,
+            V30, V31, V32, V33, V34, V35, V36, V37, V38, V39,
+            V40, V41, V42, V43, V44, V45, V46, V47, V48, V49,
+            V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
+            V60, V61, V62, V63, V64, V65, V66, V67, V68, V69,
+        }
+        impl CLike for Bar {
+            fn to_uint(&self) -> uint {
+                *self as uint
+            }
+
+            fn from_uint(v: uint) -> Bar {
+                unsafe { mem::transmute(v) }
+            }
+        }
+        let mut set = EnumSet::empty();
+        set.add(V64);
+    }
 }