summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_fs/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_fs_fs/index.c')
-rw-r--r--subversion/libsvn_fs_fs/index.c45
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,