In views_object::unpack_translatable(), recursion doesn't narrow storage correctly. For objects with hierarchical option storage, this causes the algorithm to recurse infinitely (resulting in one form of the dreaded memory exhausted error).

I discovered this problem when working with Features. One of the features was refusing to report its state (stuck in "Checking...") because memory had run out.

Patch follows.

CommentFileSizeAuthor
#1 views-1018160.patch877 byteszhangtaihao

Comments

zhangtaihao’s picture

Status: Active » Needs review
StatusFileSize
new877 bytes

I'm not sure if this patch fixes the problem correctly, but it highlights the problematic line.

The gist of the issue is that $storage is passed down in recursion as-is. This (along with a special child key present also in the parent storage) might have caused the algorithm to keep hitting the same part of the array.

dawehner’s picture

Do you know when this happens exactly? Do you have a example of a option_definition to reproduce it?

zhangtaihao’s picture

I'm not sure if the following is the option_definition triggering the problem. It's the best I can do considering each request is dumping 20000 rows into watchdog every second.

Anyway, here goes:

Array
(
    [id] => date_filter
    [table] => node
    [field] => date_filter
    [relationship] => none
    [group_type] => group
    [ui_name] => 
    [operator] => >=
    [value] => Array
        (
            [min] => Array
                (
                    [date] => 
                )

            [max] => Array
                (
                    [date] => 
                )

            [value] => Array
                (
                    [date] => 
                )

        )

    [group] => 0
    [exposed] => 
    [expose] => Array
        (
            [operator] => 
            [label] => 
            [use_operator] => 0
            [identifier] => 
            [optional] => 1
            [remember] => 0
            [single] => 1
        )

    [date_fields] => Array
        (
            [node_data_field_event_start.field_event_start_value] => node_data_field_event_start.field_event_start_value
        )

    [date_method] => OR
    [granularity] => day
    [form_type] => date_text
    [default_date] => today
    [default_to_date] => 
    [year_range] => -3:+3
)

The infinite recursion is happening in [value].

However, regardless of the problematic array structure, the code as it currently stands doesn't recurse down into the array properly anyway. For example, the [min] and [max] keys are merely skipped because the $storage array passed down simply doesn't contain those keys (and even if it did, the function wouldn't be crawling under the right trail). I suspect any value below the first level are never actually scanned.

P.S. The only reason I haven't flagged this as critical is that it's for translatables. However, I think it deserves attention because it causes out-of-memory error for us, even at 256M.

merlinofchaos’s picture

Status: Needs review » Fixed

Yes, comparing the unpack_translatable call prior to that, I agree that this patch seems correct. Committed.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.