mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-11-22 18:29:03 +01:00
gconvert: Error out if g_escape_uri_string() would overflow
If the string to escape contains a very large number of unacceptable characters (which would need escaping), the calculation of the length of the escaped string could overflow, leading to a potential write off the end of the newly allocated string. In addition to that, the number of unacceptable characters was counted in a signed integer, which would overflow to become negative, making it easier for an attacker to craft an input string which would cause an out-of-bounds write. Fix that by validating the allocation length, and using an unsigned integer to count the number of unacceptable characters. Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme from the Sovereign Tech Agency. ID: #YWH-PGM9867-134 Signed-off-by: Philip Withnall <pwithnall@gnome.org> Fixes: #3827 Backport 2.86: Changed the translatable error message to re-use an existing translatable string, to avoid adding new translatable strings to a stable branch. The re-used string doesn’t perfectly match the error, but it’s good enough given that no users will ever see it.
This commit is contained in:
@@ -1337,7 +1337,8 @@ static const gchar hex[] = "0123456789ABCDEF";
|
|||||||
* escape something else, please read RFC-2396 */
|
* escape something else, please read RFC-2396 */
|
||||||
static gchar *
|
static gchar *
|
||||||
g_escape_uri_string (const gchar *string,
|
g_escape_uri_string (const gchar *string,
|
||||||
UnsafeCharacterSet mask)
|
UnsafeCharacterSet mask,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
#define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
|
#define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
|
||||||
|
|
||||||
@@ -1345,7 +1346,7 @@ g_escape_uri_string (const gchar *string,
|
|||||||
gchar *q;
|
gchar *q;
|
||||||
gchar *result;
|
gchar *result;
|
||||||
int c;
|
int c;
|
||||||
gint unacceptable;
|
size_t unacceptable;
|
||||||
UnsafeCharacterSet use_mask;
|
UnsafeCharacterSet use_mask;
|
||||||
|
|
||||||
g_return_val_if_fail (mask == UNSAFE_ALL
|
g_return_val_if_fail (mask == UNSAFE_ALL
|
||||||
@@ -1363,6 +1364,13 @@ g_escape_uri_string (const gchar *string,
|
|||||||
unacceptable++;
|
unacceptable++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unacceptable >= (G_MAXSIZE - (p - string)) / 2)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
|
||||||
|
_("Invalid hostname"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
result = g_malloc (p - string + unacceptable * 2 + 1);
|
result = g_malloc (p - string + unacceptable * 2 + 1);
|
||||||
|
|
||||||
use_mask = mask;
|
use_mask = mask;
|
||||||
@@ -1388,11 +1396,12 @@ g_escape_uri_string (const gchar *string,
|
|||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
g_escape_file_uri (const gchar *hostname,
|
g_escape_file_uri (const gchar *hostname,
|
||||||
const gchar *pathname)
|
const gchar *pathname,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
char *escaped_hostname = NULL;
|
char *escaped_hostname = NULL;
|
||||||
char *escaped_path;
|
char *escaped_path = NULL;
|
||||||
char *res;
|
char *res = NULL;
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
char *p, *backslash;
|
char *p, *backslash;
|
||||||
@@ -1413,10 +1422,14 @@ g_escape_file_uri (const gchar *hostname,
|
|||||||
|
|
||||||
if (hostname && *hostname != '\0')
|
if (hostname && *hostname != '\0')
|
||||||
{
|
{
|
||||||
escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
|
escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST, error);
|
||||||
|
if (escaped_hostname == NULL)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH);
|
escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH, error);
|
||||||
|
if (escaped_path == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
res = g_strconcat ("file://",
|
res = g_strconcat ("file://",
|
||||||
(escaped_hostname) ? escaped_hostname : "",
|
(escaped_hostname) ? escaped_hostname : "",
|
||||||
@@ -1424,6 +1437,7 @@ g_escape_file_uri (const gchar *hostname,
|
|||||||
escaped_path,
|
escaped_path,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
out:
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
g_free ((char *) pathname);
|
g_free ((char *) pathname);
|
||||||
#endif
|
#endif
|
||||||
@@ -1757,7 +1771,7 @@ g_filename_to_uri (const gchar *filename,
|
|||||||
hostname = NULL;
|
hostname = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
escaped_uri = g_escape_file_uri (hostname, filename);
|
escaped_uri = g_escape_file_uri (hostname, filename, error);
|
||||||
|
|
||||||
return escaped_uri;
|
return escaped_uri;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user