Bug#894595: function ​cr_sel_eng_get_matched_rulesets cause denial of service

Jin Huang 54jin.huang at gmail.com
Mon Apr 2 06:42:00 BST 2018


Package: libcroco3
Version: 0.6.12-2
Severity: normal

Dear Maintainer,

The
​​
cr_sel_eng_get_matched_rulesets() function in cr-sel-eng.c can cause a
denial of service (infinite loop) via a crafted CSS file.

In the while loop(line 1378) of funtion cr_sel_eng_get_matched_rulesets(),
cr_sel_eng_get_matched_rulesets_real() will always return
"CR_OUTPUT_TOO_SHORT_ERROR" when parsing a malformed file, leading the
while loop run infinitely.

cr_sel_eng_get_matched_rulesets_real() returns  array of the ruleset
statements that matches the
given xml node, it's prototype is as below:

static enum CRStatus
cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this,
                                      CRStyleSheet * a_stylesheet,
                                      xmlNode * a_node,
                                      CRStatement ** a_rulesets,
                                      gulong * a_len)

 *@param a_sel_eng the current selection engine
 *@param a_node the xml node for which the request
 *is being made.
 *@param a_sel_list the list of selectors to perform the search in.
 *@param a_rulesets in/out parameter. A pointer to the
 *returned array of rulesets statements that match the xml node
 *given in parameter. The caller allocates the array before calling this
 *function.
 *@param a_len in/out parameter the length (in sizeof (#CRStatement*))
 *of the returned array.
 *(the length of a_rulesets, more precisely).
 *The caller must set it to the length of a_ruleset prior to calling this
 *function. In return, the function sets it to the length
 *(in sizeof (#CRStatement)) of the actually returned CRStatement array.
 *@return CR_OUTPUT_TOO_SHORT_ERROR if found more rulesets than the size
 *of the a_rulesets array. In this case, the first *a_len rulesets found
 *are put in a_rulesets, and a further call will return the following
 *ruleset(s) following the same principle.
 *@return CR_OK if all the rulesets found have been returned. In this
 *case, *a_len is set to the actual number of ruleset found.
 *@return CR_BAD_PARAM_ERROR in case any of the given parameter are
 *bad (e.g null pointer).
 *@return CR_ERROR if any other error occurred.
 */

 CR_OUTPUT_TOO_SHORT_ERROR is returned if found more rulesets than the size
of the a_rulesets array. In this case, the first *a_len rulesets found are
put in a_rulesets, and a further call will return the following ruleset(s)
following the same principle.

 However, if more than *a_len rulesets found , in a further call, the
"a_this", "a_stylesheet" and "a_node" parameter will not change. Besides,
the *a_len will always be 8 (see below) in this fuction ,thus results in
another  CR_OUTPUT_TOO_SHORT_ERROR, make the while loop run infinitely.

*a_len not changed in every call:

1355        gulong tab_size = 0,
1356                tab_len = 0,
1357                index = 0;
1358        gushort stmts_chunck_size = 8;  //stmts_chunck_size is a fixed
value

...

1375        tab_size = stmts_chunck_size;
1376        tab_len = tab_size;     //tab_size ,tab_len and
stmts_chunck_size are equal(value is 8)
1377
1378        while ((status = cr_sel_eng_get_matched_rulesets_real
1379                (a_this, a_sheet, a_node, stmts_tab + index, &tab_len))
1380               == CR_OUTPUT_TOO_SHORT_ERROR) {
1381                stmts_tab = g_try_realloc (stmts_tab,
1382                                           (tab_size +
stmts_chunck_size)
1383                                           * sizeof (CRStatement *));
1384                if (!stmts_tab) {
1385                        cr_utils_trace_info ("Out of memory");
1386                        status = CR_ERROR;
1387                        goto error;
1388                }
1389                tab_size += stmts_chunck_size;// tab_size always
incresed by 8
1390                index += tab_len;
                    // index's initial value is 0, the first time index
incresed by 8
1391                tab_len = tab_size - index;
                    /* tab_len will be 8 the first time,and causing index
always incresed by 8,
                        so in every loop ,tab_len is always 8, which will
pass to cr_sel_eng_get_matched_rulesets_real() in the further call.
                        So, in fuction
cr_sel_eng_get_matched_rulesets_real, *a_len will not changed
                        and always be 8.
                    */
1392        }



-- System Information:
Debian Release: 9.4
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.9.0-6-amd64 (SMP w/1 CPU core)
Locale: LANG=en_HK.UTF-8, LC_CTYPE=en_HK.UTF-8 (charmap=UTF-8),
LANGUAGE=en_HK:en (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages libcroco3 depends on:
ii  libc6         2.24-11+deb9u3
ii  libglib2.0-0  2.50.3-2
ii  libxml2       2.9.4+dfsg1-2.2+deb9u2


--
 Jin Huang, ADLab of Venustech
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/pkg-gnome-maintainers/attachments/20180402/7558c276/attachment-0001.html>


More information about the pkg-gnome-maintainers mailing list