mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 07:26:15 +01:00
Merge branch 'large-file-issue3' into 'main'
gfileutils: Fix g_file_get_contents() silent under-read of large files when off_t is wider than size_t See merge request GNOME/glib!3713
This commit is contained in:
commit
9c9552309a
@ -750,8 +750,8 @@ get_contents_stdio (const gchar *filename,
|
|||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
G_FILE_ERROR,
|
G_FILE_ERROR,
|
||||||
G_FILE_ERROR_NOMEM,
|
G_FILE_ERROR_NOMEM,
|
||||||
g_dngettext (GETTEXT_PACKAGE, "Could not allocate %lu byte to read file “%s”", "Could not allocate %lu bytes to read file “%s”", (gulong)total_allocated),
|
g_dngettext (GETTEXT_PACKAGE, "Could not allocate %" G_GSIZE_MODIFIER "u byte to read file “%s”", "Could not allocate %" G_GSIZE_MODIFIER "u bytes to read file “%s”", total_allocated),
|
||||||
(gulong) total_allocated,
|
total_allocated,
|
||||||
display_filename);
|
display_filename);
|
||||||
g_free (display_filename);
|
g_free (display_filename);
|
||||||
|
|
||||||
@ -831,6 +831,18 @@ get_contents_regfile (const gchar *filename,
|
|||||||
gsize alloc_size;
|
gsize alloc_size;
|
||||||
gchar *display_filename;
|
gchar *display_filename;
|
||||||
|
|
||||||
|
if ((G_MAXOFFSET >= G_MAXSIZE) && (stat_buf->st_size > (goffset) (G_MAXSIZE - 1)))
|
||||||
|
{
|
||||||
|
display_filename = g_filename_display_name (filename);
|
||||||
|
g_set_error (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
G_FILE_ERROR_FAILED,
|
||||||
|
_("File “%s” is too large"),
|
||||||
|
display_filename);
|
||||||
|
g_free (display_filename);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
size = stat_buf->st_size;
|
size = stat_buf->st_size;
|
||||||
|
|
||||||
alloc_size = size + 1;
|
alloc_size = size + 1;
|
||||||
@ -842,8 +854,8 @@ get_contents_regfile (const gchar *filename,
|
|||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
G_FILE_ERROR,
|
G_FILE_ERROR,
|
||||||
G_FILE_ERROR_NOMEM,
|
G_FILE_ERROR_NOMEM,
|
||||||
g_dngettext (GETTEXT_PACKAGE, "Could not allocate %lu byte to read file “%s”", "Could not allocate %lu bytes to read file “%s”", (gulong)alloc_size),
|
g_dngettext (GETTEXT_PACKAGE, "Could not allocate %" G_GSIZE_MODIFIER "u byte to read file “%s”", "Could not allocate %" G_GSIZE_MODIFIER "u bytes to read file “%s”", alloc_size),
|
||||||
(gulong) alloc_size,
|
alloc_size,
|
||||||
display_filename);
|
display_filename);
|
||||||
g_free (display_filename);
|
g_free (display_filename);
|
||||||
goto error;
|
goto error;
|
||||||
@ -891,7 +903,7 @@ get_contents_regfile (const gchar *filename,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
|
|
||||||
|
@ -1474,6 +1474,121 @@ test_get_contents (void)
|
|||||||
g_remove (filename);
|
g_remove (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
resize_file (const gchar *filename,
|
||||||
|
gint64 size)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
fd = g_open (filename, O_CREAT | O_RDWR | O_TRUNC, 0666);
|
||||||
|
g_assert_cmpint (fd, >=, 0);
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
retval = _chsize_s (fd, size);
|
||||||
|
#else
|
||||||
|
retval = ftruncate64 (fd, size);
|
||||||
|
#endif
|
||||||
|
if (retval != 0)
|
||||||
|
{
|
||||||
|
g_test_message ("Error trying to resize file (%s)", strerror (errno));
|
||||||
|
close (fd);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_error_in_list (GFileError error_code,
|
||||||
|
const GFileError ok_list[],
|
||||||
|
size_t ok_count)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < ok_count; i++)
|
||||||
|
{
|
||||||
|
if (ok_list[i] == error_code)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_largefile_check_len (const gchar *filename,
|
||||||
|
gint64 large_len,
|
||||||
|
const GFileError ok_list[],
|
||||||
|
size_t ok_count)
|
||||||
|
{
|
||||||
|
gboolean get_ok;
|
||||||
|
gsize len;
|
||||||
|
gchar *contents;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
get_ok = g_file_get_contents (filename, &contents, &len, &error);
|
||||||
|
if (get_ok)
|
||||||
|
{
|
||||||
|
g_assert_cmpint ((gint64) len, ==, large_len);
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_cmpint (error->domain, ==, G_FILE_ERROR);
|
||||||
|
if (is_error_in_list ((GFileError)error->code, ok_list, ok_count))
|
||||||
|
{
|
||||||
|
g_test_message ("Error reading file of size 0x%" G_GINT64_MODIFIER "x, but with acceptable error type (%s)", large_len, error->message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fail for other errors */
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_get_contents_largefile (void)
|
||||||
|
{
|
||||||
|
if (!g_test_slow ())
|
||||||
|
{
|
||||||
|
g_test_skip ("Skipping slow largefile test");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *filename = "file-test-get-contents-large";
|
||||||
|
gint64 large_len;
|
||||||
|
|
||||||
|
/* error OK if couldn't allocate large buffer, or if file is too large */
|
||||||
|
const GFileError too_large_errors[] = { G_FILE_ERROR_NOMEM, G_FILE_ERROR_FAILED };
|
||||||
|
/* error OK if couldn't allocate large buffer */
|
||||||
|
const GFileError nomem_errors[] = { G_FILE_ERROR_NOMEM };
|
||||||
|
|
||||||
|
/* OK to fail to read this, but don't silently under-read */
|
||||||
|
large_len = (G_GINT64_CONSTANT (1) << 32) + 16;
|
||||||
|
if (!resize_file (filename, large_len))
|
||||||
|
goto failed_resize;
|
||||||
|
get_largefile_check_len (filename, large_len, too_large_errors, G_N_ELEMENTS (too_large_errors));
|
||||||
|
|
||||||
|
/* OK to fail to read this size, but don't silently under-read */
|
||||||
|
large_len = (G_GINT64_CONSTANT (1) << 32) - 1;
|
||||||
|
if (!resize_file (filename, large_len))
|
||||||
|
goto failed_resize;
|
||||||
|
get_largefile_check_len (filename, large_len, too_large_errors, G_N_ELEMENTS (too_large_errors));
|
||||||
|
|
||||||
|
/* OK to fail memory allocation, but don't otherwise fail this size */
|
||||||
|
large_len = (G_GINT64_CONSTANT (1) << 31) - 1;
|
||||||
|
if (!resize_file (filename, large_len))
|
||||||
|
goto failed_resize;
|
||||||
|
get_largefile_check_len (filename, large_len, nomem_errors, G_N_ELEMENTS (nomem_errors));
|
||||||
|
|
||||||
|
g_remove (filename);
|
||||||
|
return;
|
||||||
|
|
||||||
|
failed_resize:
|
||||||
|
g_test_incomplete ("Failed to resize large file, unable to complete large file tests.");
|
||||||
|
g_remove (filename);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_file_test (void)
|
test_file_test (void)
|
||||||
{
|
{
|
||||||
@ -2648,6 +2763,7 @@ main (int argc,
|
|||||||
g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
|
g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
|
||||||
g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
|
g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
|
||||||
g_test_add_func ("/fileutils/get-contents", test_get_contents);
|
g_test_add_func ("/fileutils/get-contents", test_get_contents);
|
||||||
|
g_test_add_func ("/fileutils/get-contents-large-file", test_get_contents_largefile);
|
||||||
g_test_add_func ("/fileutils/set-contents", test_set_contents);
|
g_test_add_func ("/fileutils/set-contents", test_set_contents);
|
||||||
g_test_add_func ("/fileutils/set-contents-full", test_set_contents_full);
|
g_test_add_func ("/fileutils/set-contents-full", test_set_contents_full);
|
||||||
g_test_add_func ("/fileutils/set-contents-full/read-only-file", test_set_contents_full_read_only_file);
|
g_test_add_func ("/fileutils/set-contents-full/read-only-file", test_set_contents_full_read_only_file);
|
||||||
|
Loading…
Reference in New Issue
Block a user