diff options
Diffstat (limited to 'subversion/libsvn_diff/diff_file.c')
-rw-r--r-- | subversion/libsvn_diff/diff_file.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/subversion/libsvn_diff/diff_file.c b/subversion/libsvn_diff/diff_file.c index e70c2f9..830552a 100644 --- a/subversion/libsvn_diff/diff_file.c +++ b/subversion/libsvn_diff/diff_file.c @@ -166,26 +166,39 @@ read_chunk(apr_file_t *file, const char *path, static svn_error_t * map_or_read_file(apr_file_t **file, MMAP_T_PARAM(mm) - char **buffer, apr_off_t *size, + char **buffer, apr_size_t *size_p, const char *path, apr_pool_t *pool) { apr_finfo_t finfo; apr_status_t rv; + apr_size_t size; *buffer = NULL; SVN_ERR(svn_io_file_open(file, path, APR_READ, APR_OS_DEFAULT, pool)); SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, *file, pool)); + if (finfo.size > APR_SIZE_MAX) + { + return svn_error_createf(APR_ENOMEM, NULL, + _("File '%s' is too large to be read in " + "to memory"), path); + } + + size = (apr_size_t) finfo.size; #if APR_HAS_MMAP - if (finfo.size > APR_MMAP_THRESHOLD) + if (size > APR_MMAP_THRESHOLD) { - rv = apr_mmap_create(mm, *file, 0, (apr_size_t) finfo.size, - APR_MMAP_READ, pool); + rv = apr_mmap_create(mm, *file, 0, size, APR_MMAP_READ, pool); if (rv == APR_SUCCESS) { *buffer = (*mm)->mm; } + else + { + /* Clear *MM because output parameters are undefined on error. */ + *mm = NULL; + } /* On failure we just fall through and try reading the file into * memory instead. @@ -193,12 +206,11 @@ map_or_read_file(apr_file_t **file, } #endif /* APR_HAS_MMAP */ - if (*buffer == NULL && finfo.size > 0) + if (*buffer == NULL && size > 0) { - *buffer = apr_palloc(pool, (apr_size_t) finfo.size); + *buffer = apr_palloc(pool, size); - SVN_ERR(svn_io_file_read_full2(*file, *buffer, (apr_size_t) finfo.size, - NULL, NULL, pool)); + SVN_ERR(svn_io_file_read_full2(*file, *buffer, size, NULL, NULL, pool)); /* Since we have the entire contents of the file we can * close it now. @@ -208,7 +220,7 @@ map_or_read_file(apr_file_t **file, *file = NULL; } - *size = finfo.size; + *size_p = size; return SVN_NO_ERROR; } @@ -2360,7 +2372,7 @@ svn_diff_file_output_merge2(svn_stream_t *output_stream, for (idx = 0; idx < 3; idx++) { - apr_off_t size; + apr_size_t size; SVN_ERR(map_or_read_file(&file[idx], MMAP_T_ARG(mm[idx]) |