diff options
author | Egmont Koblinger <egmont@gmail.com> | 2015-04-28 23:51:21 +0200 |
---|---|---|
committer | Egmont Koblinger <egmont@gmail.com> | 2015-04-28 23:51:21 +0200 |
commit | 5e41c83e31157a7c6008e7d50d15c6e9f9e5b8f0 (patch) | |
tree | 463ace09590e3d655cfb62a38b947be8c67a2a3d | |
parent | 9d56f7fe2e196981dc1028798b7ebc96d1d63a58 (diff) | |
download | vte-5e41c83e31157a7c6008e7d50d15c6e9f9e5b8f0.tar.gz |
stream: Fix a crash on truncate followed by reset0.40.2
https://bugzilla.gnome.org/show_bug.cgi?id=748484
(cherry picked from commit a235384892c617c961cd1c9131227f8b1363fa22)
-rw-r--r-- | src/vtestream-file.h | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/src/vtestream-file.h b/src/vtestream-file.h index bcd68df9..779587d0 100644 --- a/src/vtestream-file.h +++ b/src/vtestream-file.h @@ -385,16 +385,24 @@ _vte_snake_ensure_file (VteSnake *snake) snake->fd = _vte_mkstemp (); } +static void _vte_snake_advance_tail (VteSnake *snake, gsize offset); static void _vte_snake_reset (VteSnake *snake, gsize offset) { g_assert_cmpuint (offset % VTE_SNAKE_BLOCKSIZE, ==, 0); - _file_reset (snake->fd); + /* See the comments in _vte_boa_reset(). */ + g_assert_cmpuint (offset, >=, snake->tail); - snake->segment[0].st_tail = snake->segment[0].st_head = snake->tail = snake->head = offset; - snake->segment[0].fd_tail = snake->segment[0].fd_head = 0; - snake->state = 1; + if (G_LIKELY (offset >= snake->head)) { + _file_reset (snake->fd); + snake->segment[0].st_tail = snake->segment[0].st_head = snake->tail = snake->head = offset; + snake->segment[0].fd_tail = snake->segment[0].fd_head = 0; + snake->state = 1; + } else { + /* Never retreat the head: bug 748484. */ + _vte_snake_advance_tail (snake, offset); + } } /* @@ -845,14 +853,20 @@ _vte_boa_reset (VteBoa *boa, gsize offset) { g_assert_cmpuint (offset % VTE_BOA_BLOCKSIZE, ==, 0); - /* _vte_ring_reset() is designed never to actually reset the logical offset. - * It's important for the encryption so that we don't reuse the same IV. - * Hence this is probably the best place to double check this. */ - g_assert_cmpuint (offset, >=, boa->head); + /* _vte_ring_reset() requires the new offset not to be in the + * offset region that we've left behind for good. This is so that + * if we write at a position that we've already written previously, + * we're aware of it and can read back and increment the overwrite + * counter. This is important for the encryption so that we don't + * reuse the same IV. For the same reason, we never retreat the + * head of the stream. See bug 748484. */ + g_assert_cmpuint (offset, >=, boa->tail); _vte_snake_reset (&boa->parent, OFFSET_BOA_TO_SNAKE(offset)); - boa->tail = boa->head = offset; + boa->tail = offset; + /* Never retreat the head: bug 748484. */ + boa->head = MAX(boa->head, offset); } /* Place VTE_BOA_BLOCKSIZE bytes at data. @@ -1373,9 +1387,9 @@ test_snake (void) assert_file (snake->fd, "Duck......Chinchilla..........Ferret...."); assert_snake (snake, 1, 0, 40, "Duck......Chinchilla..........Ferret...."); - /* Reset */ - _vte_snake_reset (snake, 0); - assert_snake (snake, 1, 0, 0, ""); + /* Start over */ + g_object_unref (snake); + snake = g_object_new (VTE_TYPE_SNAKE, NULL); /* State 1 */ snake_write (snake, 0, "Armadillo"); @@ -1437,6 +1451,16 @@ test_snake (void) g_object_unref (snake); } +/* 10-byte blocks in the file and snake layers consist of: + * - 1 byte: length of the fake-compressed, fake-encrypted payload (n) + * - 1 byte: overwrite counter for the given block + * - n bytes: fake-compressed (if could indeed be compressed), fake-encrypted payload + * - 1 byte: fake checksum: + * - 2 octal digits: block sequence number + * - 1 octal digit: overwrite counter + * - 7-n bytes: dots for padding + */ + static void test_boa (void) { @@ -1706,6 +1730,24 @@ test_stream (void) assert_boa (boa, 175, 182, "zebraaa"); assert_stream (astream, 175, 182, "zebraaa"); + /* Bug 748484: cross-boundary truncate followed by a reset */ + _vte_stream_truncate (astream, 178); + assert_file (snake->fd, "\007\001ZEBRAAA\311"); + assert_snake (snake, 1, 250, 260, "\007\001ZEBRAAA\311"); + assert_boa (boa, 175, 182, "zebraaa"); + assert_stream (astream, 175, 178, "zeb"); + _vte_stream_reset (astream, 178); + /* Snake and boa don't drop the data */ + assert_file (snake->fd, "\007\001ZEBRAAA\311"); + assert_snake (snake, 1, 250, 260, "\007\001ZEBRAAA\311"); + assert_boa (boa, 175, 182, "zebraaa"); + assert_stream (astream, 178, 178, ""); + stream_append (astream, "raaa"); + assert_file (snake->fd, "\006\0023-1R3A\312."); + assert_snake (snake, 1, 250, 260, "\006\0023-1R3A\312."); + assert_boa (boa, 175, 182, "---raaa"); + assert_stream (astream, 178, 182, "raaa"); + g_object_unref (astream); } |