diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index 363dbd88fb7..ff61ef15fa5 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -10,7 +10,6 @@
 
 //! Readers and Writers for in-memory buffers
 
-use cmp::max;
 use cmp::min;
 use container::Container;
 use option::None;
@@ -20,6 +19,25 @@ use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
 use vec;
 use vec::{Vector, ImmutableVector, MutableVector, OwnedCloneableVector};
 
+fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
+    // compute offset as signed and clamp to prevent overflow
+    let pos = match seek {
+        SeekSet => 0,
+        SeekEnd => end,
+        SeekCur => cur,
+    } as i64;
+
+    if offset + pos < 0 {
+        Err(IoError {
+            kind: io::InvalidInput,
+            desc: "invalid seek to a negative offset",
+            detail: None
+        })
+    } else {
+        Ok((offset + pos) as u64)
+    }
+}
+
 /// Writes to an owned, growable byte vector
 ///
 /// # Example
@@ -92,19 +110,11 @@ impl Writer for MemWriter {
     }
 }
 
-// FIXME(#10432)
 impl Seek for MemWriter {
     fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-
     fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
-        // compute offset as signed and clamp to prevent overflow
-        let offset = match style {
-            SeekSet => { 0 }
-            SeekEnd => { self.buf.len() }
-            SeekCur => { self.pos }
-        } as i64;
-
-        self.pos = max(0, offset+pos) as uint;
+        let new = if_ok!(combine(style, self.pos, self.buf.len(), pos));
+        self.pos = new as uint;
         Ok(())
     }
 }
@@ -139,7 +149,7 @@ impl MemReader {
     /// Tests whether this reader has read all bytes in its buffer.
     ///
     /// If `true`, then this will no longer return bytes from `read`.
-    pub fn eof(&self) -> bool { self.pos == self.buf.len() }
+    pub fn eof(&self) -> bool { self.pos >= self.buf.len() }
 
     /// Acquires an immutable reference to the underlying buffer of this
     /// `MemReader`.
@@ -172,7 +182,11 @@ impl Reader for MemReader {
 
 impl Seek for MemReader {
     fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-    fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() }
+    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+        let new = if_ok!(combine(style, self.pos, self.buf.len(), pos));
+        self.pos = new as uint;
+        Ok(())
+    }
 }
 
 impl Buffer for MemReader {
@@ -236,24 +250,15 @@ impl<'a> Writer for BufWriter<'a> {
     }
 }
 
-// FIXME(#10432)
 impl<'a> Seek for BufWriter<'a> {
     fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-
     fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
-        // compute offset as signed and clamp to prevent overflow
-        let offset = match style {
-            SeekSet => { 0 }
-            SeekEnd => { self.buf.len() }
-            SeekCur => { self.pos }
-        } as i64;
-
-        self.pos = max(0, offset+pos) as uint;
+        let new = if_ok!(combine(style, self.pos, self.buf.len(), pos));
+        self.pos = new as uint;
         Ok(())
     }
 }
 
-
 /// Reads from a fixed-size byte slice
 ///
 /// # Example
@@ -284,7 +289,7 @@ impl<'a> BufReader<'a> {
     /// Tests whether this reader has read all bytes in its buffer.
     ///
     /// If `true`, then this will no longer return bytes from `read`.
-    pub fn eof(&self) -> bool { self.pos == self.buf.len() }
+    pub fn eof(&self) -> bool { self.pos >= self.buf.len() }
 }
 
 impl<'a> Reader for BufReader<'a> {
@@ -307,7 +312,11 @@ impl<'a> Reader for BufReader<'a> {
 
 impl<'a> Seek for BufReader<'a> {
     fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-    fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() }
+    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
+        let new = if_ok!(combine(style, self.pos, self.buf.len(), pos));
+        self.pos = new as uint;
+        Ok(())
+    }
 }
 
 impl<'a> Buffer for BufReader<'a> {
@@ -506,4 +515,42 @@ mod test {
             Err(..) => {}
         }
     }
+
+    #[test]
+    fn seek_past_end() {
+        let buf = [0xff];
+        let mut r = BufReader::new(buf);
+        r.seek(10, SeekSet).unwrap();
+        assert!(r.read(&mut []).is_err());
+
+        let mut r = MemReader::new(~[10]);
+        r.seek(10, SeekSet).unwrap();
+        assert!(r.read(&mut []).is_err());
+
+        let mut r = MemWriter::new();
+        r.seek(10, SeekSet).unwrap();
+        assert!(r.write([3]).is_ok());
+
+        let mut buf = [0];
+        let mut r = BufWriter::new(buf);
+        r.seek(10, SeekSet).unwrap();
+        assert!(r.write([3]).is_err());
+    }
+
+    #[test]
+    fn seek_before_0() {
+        let buf = [0xff];
+        let mut r = BufReader::new(buf);
+        assert!(r.seek(-1, SeekSet).is_err());
+
+        let mut r = MemReader::new(~[10]);
+        assert!(r.seek(-1, SeekSet).is_err());
+
+        let mut r = MemWriter::new();
+        assert!(r.seek(-1, SeekSet).is_err());
+
+        let mut buf = [0];
+        let mut r = BufWriter::new(buf);
+        assert!(r.seek(-1, SeekSet).is_err());
+    }
 }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 1c1df691a52..41f7e555755 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1192,19 +1192,21 @@ pub enum SeekStyle {
     SeekCur,
 }
 
-/// # FIXME
-/// * Are `u64` and `i64` the right choices?
 pub trait Seek {
     /// Return position of file cursor in the stream
     fn tell(&self) -> IoResult<u64>;
 
     /// Seek to an offset in a stream
     ///
-    /// A successful seek clears the EOF indicator.
+    /// A successful seek clears the EOF indicator. Seeking beyond EOF is
+    /// allowed, but seeking before position 0 is not allowed.
     ///
-    /// # FIXME
+    /// # Errors
     ///
-    /// * What is the behavior when seeking past the end of a stream?
+    /// * Seeking to a negative offset is considered an error
+    /// * Seeking past the end of the stream does not modify the underlying
+    ///   stream, but the next write may cause the previous data to be filled in
+    ///   with a bit pattern.
     fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()>;
 }