<div dir="ltr"><div>Package: libcroco3</div><div>Version: 0.6.12-2</div><div>Severity: normal</div><div><br></div><div>Dear Maintainer,</div><div><br></div><div>The <div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​​</div>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. </div><div><br></div><div>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.</div><div> </div><div>cr_sel_eng_get_matched_rulesets_real() returns  array of the ruleset statements that matches the</div><div>given xml node, it's prototype is as below:</div><div><br></div><div>static enum CRStatus</div><div>cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this,</div><div>                                      CRStyleSheet * a_stylesheet,</div><div>                                      xmlNode * a_node,</div><div>                                      CRStatement ** a_rulesets,</div><div>                                      gulong * a_len)</div><div>                                      </div><div> *@param a_sel_eng the current selection engine</div><div> *@param a_node the xml node for which the request</div><div> *is being made.</div><div> *@param a_sel_list the list of selectors to perform the search in.</div><div> *@param a_rulesets in/out parameter. A pointer to the</div><div> *returned array of rulesets statements that match the xml node</div><div> *given in parameter. The caller allocates the array before calling this</div><div> *function.</div><div> *@param a_len in/out parameter the length (in sizeof (#CRStatement*)) </div><div> *of the returned array.</div><div> *(the length of a_rulesets, more precisely).</div><div> *The caller must set it to the length of a_ruleset prior to calling this</div><div> *function. In return, the function sets it to the length </div><div> *(in sizeof (#CRStatement)) of the actually returned CRStatement array.</div><div> *@return CR_OUTPUT_TOO_SHORT_ERROR if found more rulesets than the size</div><div> *of the a_rulesets array. In this case, the first *a_len rulesets found</div><div> *are put in a_rulesets, and a further call will return the following</div><div> *ruleset(s) following the same principle.</div><div> *@return CR_OK if all the rulesets found have been returned. In this</div><div> *case, *a_len is set to the actual number of ruleset found.</div><div> *@return CR_BAD_PARAM_ERROR in case any of the given parameter are</div><div> *bad (e.g null pointer).</div><div> *@return CR_ERROR if any other error occurred.</div><div> */</div><div><br></div><div> 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.</div><div> </div><div> 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. </div><div><br></div><div>*a_len not changed in every call:</div><div> </div><div>1355        gulong tab_size = 0,</div><div>1356                tab_len = 0,</div><div>1357                index = 0;</div><div>1358        gushort stmts_chunck_size = 8;  //stmts_chunck_size is a fixed value</div><div><br></div><div>...</div><div><br></div><div>1375        tab_size = stmts_chunck_size;   </div><div>1376        tab_len = tab_size;     //tab_size ,tab_len and stmts_chunck_size are equal(value is 8)</div><div>1377</div><div>1378        while ((status = cr_sel_eng_get_matched_rulesets_real</div><div>1379                (a_this, a_sheet, a_node, stmts_tab + index, &tab_len))</div><div>1380               == CR_OUTPUT_TOO_SHORT_ERROR) {</div><div>1381                stmts_tab = g_try_realloc (stmts_tab,</div><div>1382                                           (tab_size + stmts_chunck_size)</div><div>1383                                           * sizeof (CRStatement *));</div><div>1384                if (!stmts_tab) {</div><div>1385                        cr_utils_trace_info ("Out of memory");</div><div>1386                        status = CR_ERROR;</div><div>1387                        goto error;</div><div>1388                }</div><div>1389                tab_size += stmts_chunck_size;// tab_size always incresed by 8</div><div>1390                index += tab_len;   </div><div>                    // index's initial value is 0, the first time index incresed by 8 </div><div>1391                tab_len = tab_size - index; </div><div>                    /* tab_len will be 8 the first time,and causing index always incresed by 8,</div><div>                        so in every loop ,tab_len is always 8, which will pass to cr_sel_eng_get_matched_rulesets_real() in the further call.</div><div>                        So, in fuction cr_sel_eng_get_matched_rulesets_real, *a_len will not changed</div><div>                        and always be 8.</div><div>                    */</div><div>1392        }</div><div><br></div><div><br></div><div><br></div><div>-- System Information:</div><div>Debian Release: 9.4</div><div>  APT prefers stable-updates</div><div>  APT policy: (500, 'stable-updates'), (500, 'stable')</div><div>Architecture: amd64 (x86_64)</div><div><br></div><div>Kernel: Linux 4.9.0-6-amd64 (SMP w/1 CPU core)</div><div>Locale: LANG=en_HK.UTF-8, LC_CTYPE=en_HK.UTF-8 (charmap=UTF-8), LANGUAGE=en_HK:en (charmap=UTF-8)</div><div>Shell: /bin/sh linked to /bin/dash</div><div>Init: systemd (via /run/systemd/system)</div><div><br></div><div>Versions of packages libcroco3 depends on:</div><div>ii  libc6         2.24-11+deb9u3</div><div>ii  libglib2.0-0  2.50.3-2</div><div>ii  libxml2       2.9.4+dfsg1-2.2+deb9u2</div><div><br></div><div><br></div><div>--</div><div> Jin Huang, ADLab of Venustech</div></div>