Project

General

Profile

Actions

Bug #11383

closed

Infinite loop in str_buf_cat triggered by str_gsub

Added by lfarcy (Laurent Farcy) almost 9 years ago. Updated over 8 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
[ruby-core:70074]

Description

I've got a Ruby program which reads some RSS/Atom feeds to load each of them into a relational database. It makes use of a modified version of SimpleRSS v1.2.

After moving to Ruby 2.2.2, I observe 100% CPU usage from time to time. Using gdb, I was able to identify the culprit: it's a call to str_buf_cat from str_gsub. Here's the section of code that loops in string.c (from line 2198 til line 2204).

	while (total > capa) {
	    if (capa > LONG_MAX / 2) {
		capa = (total + 4095) / 4096 * 4096;
		break;
	    }
	    capa = 2 * capa;
	}

capa is equal to 0 when the while block infinitely loops. I guess it's somehow unexpected...

Unfortunately, since the VM is looping, I cannot determine the piece of 'my' code where gsub is used. rb_eval, as found in https://github.com/michaelklishin/gdb-macros-for-ruby/blob/master/gdb_macros_for_ruby, cannot work because rb_finish cannot terminate.

But I was able to dump the backtrace and all the args and locals that lead to the infinite loop.


Files

bug-11383.log (22.8 KB) bug-11383.log nobu (Nobuyoshi Nakada), 07/22/2015 07:15 AM

Updated by nobu (Nobuyoshi Nakada) almost 9 years ago

Very interesting.
An empty string is usually embedding, and I can't tell why there is an empty non-embed string.
Couldn't you show its content, *(struct RString *)str?

Updated by nobu (Nobuyoshi Nakada) almost 9 years ago

  • Status changed from Open to Feedback

Updated by lfarcy (Laurent Farcy) almost 9 years ago

Nobuyoshi Nakada wrote:

Very interesting.
An empty string is usually embedding, and I can't tell why there is an empty non-embed string.
Couldn't you show its content, *(struct RString *)str?

I'll submit the content of *(struct RString *)str as soon as the issue reproduces. I'm sure it will since it has happened many times for those last weeks.

I had to kill the previous ever-looping processes because they took too much CPU on our production server.

Actions #4

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Status changed from Feedback to Closed

Applied in changeset r51428.


string.c: empty non-embed case

  • string.c (str_buf_cat): consider empty non-embed string case,
    not to loop infinitely. [ruby-core:70074] [Bug #11383]

Updated by lfarcy (Laurent Farcy) over 8 years ago

Nobu,

Thanks for fixing this issue.

On our side, the issue reproduced, not with the same arguments though. Anyway, I was able to get the value of *(struct RString *)str.

(gdb) display *(struct RString *)str
1: *(struct RString *)str = {basic = {flags = 4202501, klass = 30232280}, as = {heap = {len = 0, ptr = 0x0, aux = {capa = 0, shared = 0}}, ary = '\000' <repeats 23 times>}}

I wish it could be consistent with the fix you made.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0