Skip to content

Potentially uninitialized variable causes random parsing failure of the field CALC #35

@hanak

Description

@hanak

In our solution, I noticed that sCalcout (scalc R3-7-4) failed to parse the following CALC on Linux (Ubuntu 22) but succeeded on Windows:

CC:=BB;BB:=AA;F:=E;E:=D;H:=G;G:=1;(AA#CC)|(D#F)|(H=0)

When I enabled logs (sCalcPostfixDebug=5), I got following sequences:

  • Linux:

    get_element:FETCH_CC (CC) runtime_depth=0
    get_element:STORE_A (:=) runtime_depth=1
    get_element:FETCH_BB (BB) runtime_depth=0
    get_element:NOT_GENERATED (;) runtime_depth=1
    get_element:FETCH_BB (BB) runtime_depth=1
    get_element:STORE_A (:=) runtime_depth=2
    STORE_OPERATOR:pout[-1] is a string fetch
    ...
    
  • Windows:

    get_element:FETCH_CC (CC) runtime_depth=0
    get_element:STORE_A (:=) runtime_depth=1
    STORE_OPERATOR:pout[-1] is a string fetch
    get_element:FETCH_BB (BB) runtime_depth=0
    get_element:NOT_GENERATED (;) runtime_depth=1
    EXPR_TERMINATOR op ';': moved ':=' from stack
    get_element:FETCH_BB (BB) runtime_depth=0
    get_element:STORE_A (:=) runtime_depth=1
    STORE_OPERATOR:pout[-1] is a string fetch
    

I tried to identify the source and came up with the following observation:

  • It all happens inside sCalcPostfix().
  • Before the processing loop, pstacktop points at stack.
  • The first token to be processed is FETCH_CC. That is an OPERAND and does nothing with pstacktop.
  • The next token is STORE_A is processed. That is a STORE_OPERATOR. Since pstacktop == stack at this time, the loop in case STORE_OPERATOR exits immediately. It leaves ps1 set to stack. Yet, stack has not been updated/written yet. So, it contains random garbage from memory. Luckily enough, this garbage happen to cause ps1->code == A_FETCH which sets handled to 1 and sends the code towards different path than on Windows.

Just to test the idea, I tried to memset the first item of stack to 0 (code 0 means END_EXPRESSION which seems to be safe) prior to entering the processing loop. And, sCalcout parsed the expression right (no error). I admit I did not run a test IOC with calc only. I tried to insert the expression into scalcTest but it parsed without any problem unless I injected stack[0].code = A_FETCH right after declaring stack.

Do you see this as something to fix? I can try to prepare a pull request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions