diff options
Diffstat (limited to 'subversion/libsvn_fs_fs/index.c')
-rw-r--r-- | subversion/libsvn_fs_fs/index.c | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/subversion/libsvn_fs_fs/index.c b/subversion/libsvn_fs_fs/index.c index a6695580a0f5f..1cb8fba80ad61 100644 --- a/subversion/libsvn_fs_fs/index.c +++ b/subversion/libsvn_fs_fs/index.c @@ -231,7 +231,7 @@ stream_error_create(svn_fs_fs__packed_number_stream_t *stream, apr_off_t offset; SVN_ERR(svn_io_file_name_get(&file_name, stream->file, stream->pool)); - SVN_ERR(svn_fs_fs__get_file_offset(&offset, stream->file, stream->pool)); + SVN_ERR(svn_io_file_get_offset(&offset, stream->file, stream->pool)); return svn_error_createf(err, NULL, message, file_name, apr_psprintf(stream->pool, @@ -251,7 +251,7 @@ static svn_error_t * packed_stream_read(svn_fs_fs__packed_number_stream_t *stream) { unsigned char buffer[MAX_NUMBER_PREFETCH]; - apr_size_t read = 0; + apr_size_t bytes_read = 0; apr_size_t i; value_position_pair_t *target; apr_off_t block_start = 0; @@ -273,33 +273,34 @@ packed_stream_read(svn_fs_fs__packed_number_stream_t *stream) * boundaries. This shall prevent jumping back and forth between two * blocks because the extra data was not actually request _now_. */ - read = sizeof(buffer); + bytes_read = sizeof(buffer); block_left = stream->block_size - (stream->next_offset - block_start); - if (block_left >= 10 && block_left < read) - read = (apr_size_t)block_left; + if (block_left >= 10 && block_left < bytes_read) + bytes_read = (apr_size_t)block_left; /* Don't read beyond the end of the file section that belongs to this * index / stream. */ - read = (apr_size_t)MIN(read, stream->stream_end - stream->next_offset); + bytes_read = (apr_size_t)MIN(bytes_read, + stream->stream_end - stream->next_offset); - err = apr_file_read(stream->file, buffer, &read); + err = apr_file_read(stream->file, buffer, &bytes_read); if (err && !APR_STATUS_IS_EOF(err)) return stream_error_create(stream, err, _("Can't read index file '%s' at offset 0x%s")); /* if the last number is incomplete, trim it from the buffer */ - while (read > 0 && buffer[read-1] >= 0x80) - --read; + while (bytes_read > 0 && buffer[bytes_read-1] >= 0x80) + --bytes_read; /* we call read() only if get() requires more data. So, there must be * at least *one* further number. */ - if SVN__PREDICT_FALSE(read == 0) + if SVN__PREDICT_FALSE(bytes_read == 0) return stream_error_create(stream, err, _("Unexpected end of index file %s at offset 0x%s")); /* parse file buffer and expand into stream buffer */ target = stream->buffer; - for (i = 0; i < read;) + for (i = 0; i < bytes_read;) { if (buffer[i] < 0x80) { @@ -558,13 +559,13 @@ read_uint64_from_proto_index(apr_file_t *proto_index, apr_pool_t *scratch_pool) { apr_byte_t buffer[sizeof(*value_p)]; - apr_size_t read; + apr_size_t bytes_read; /* Read the full 8 bytes or our 64 bit value, unless we hit EOF. * Assert that we never read partial values. */ SVN_ERR(svn_io_file_read_full2(proto_index, buffer, sizeof(buffer), - &read, eof, scratch_pool)); - SVN_ERR_ASSERT((eof && *eof) || read == sizeof(buffer)); + &bytes_read, eof, scratch_pool)); + SVN_ERR_ASSERT((eof && *eof) || bytes_read == sizeof(buffer)); /* If we did not hit EOF, reconstruct the uint64 value and return it. */ if (!eof || !*eof) @@ -1735,7 +1736,7 @@ svn_fs_fs__l2p_get_max_ids(apr_array_header_t **max_ids, apr_uint64_t item_count; apr_size_t first_page_index, last_page_index; - if (revision >= header->first_revision + header->revision_count) + if (revision - header->first_revision >= header->revision_count) { /* need to read the next index. Clear up memory used for the * previous one. Note that intermittent pack runs do not change @@ -2421,6 +2422,13 @@ read_entry(svn_fs_fs__packed_number_stream_t *stream, return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Empty regions must have item number 0 and checksum 0")); + /* Corrupted SIZE values might cause arithmetic overflow. + * The same can happen if you copy a repository from a system with 63 bit + * file lengths to one with 31 bit file lengths. */ + if ((apr_uint64_t)entry.offset + (apr_uint64_t)entry.size > off_t_max) + return svn_error_create(SVN_ERR_FS_INDEX_OVERFLOW , NULL, + _("P2L index entry size overflow.")); + APR_ARRAY_PUSH(result, svn_fs_fs__p2l_entry_t) = entry; *item_offset += entry.size; @@ -3207,18 +3215,11 @@ svn_fs_fs__l2p_index_from_p2l_entries(const char **protoname, apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; svn_revnum_t last_revision = SVN_INVALID_REVNUM; - svn_revnum_t revision = SVN_INVALID_REVNUM; /* L2P index must be written in revision order. * Sort ENTRIES accordingly. */ svn_sort__array(entries, compare_p2l_entry_revision); - /* Find the first revision in the index - * (must exist since no truly empty revs are allowed). */ - for (i = 0; i < entries->nelts && !SVN_IS_VALID_REVNUM(revision); ++i) - revision = APR_ARRAY_IDX(entries, i, const svn_fs_fs__p2l_entry_t *) - ->item.revision; - /* Create the temporary proto-rev file. */ SVN_ERR(svn_io_open_unique_file3(NULL, protoname, NULL, svn_io_file_del_on_pool_cleanup, |