Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Anti-Aliasing Bug (Initialize pre-generated message, then modify it)  #274

@RafaelLaya

Description

@RafaelLaya

bug_for_flatcc.zip

Hi everyone! This is my first bug report contribution into the FlatCC project. Thanks for making such an awesome project! Here are the details:

Files attached

  • build.sh has the build command to repro (define $GCC_PATH)
  • version.txt has GCC version (latest none-eabi) -- I was very close to filing a GCC bug until I turned on -fno-strict-aliasing and realized the issue is with the aliasing in FlatCC, not with the compiler
  • tempfiles.c The source code, after the preprocessor pasted the generated FlatCC code. Note the suffix "v2" is added by me by hand before posting here, not generated
  • out.lst The dissasembly

Explanation of the source code provided in tempfiles.c

The code in question is in the function interface_encoding_populate_general_rsp(). writes a message determined at compile-time into an array in the stack, and then finishes the message and copies into a buffer given by the caller.

If one steps through the code, essentially the following happens:

  • Response_as_root_v2() reads the word at msg_array[0] which should be equal to 12 and returns &msg_array[12]
  • Response_data_v2() reads the word at msg_array[12] which should be equal to 8 and then finds &msg_array[12-8]=&msg_array[4]. Then reads half-word at msg_array[4] and checks whether it is >=8. If less, it asserts

From the initialization of msg_array we can see everything should be initialized correctly, then Response_as_root_v2() and Reponse_data_v2() will work exactly as described above.

Actual Issue

The compiler smartly determines that it needs to look at msg_array[4] and check if it is less than 8. However, it reads msg_array[4] into R5 which has garbage in the stack. Then it initializes msg_array in the stack, and then compares R5 with 7 (branches to assert if less-or-equal). The problem is that by the time the comparison is done, the array is partly initialized and R5 has garbage from the stack before the initialization of the array

a: f8bd 5004 ldrh.w r5, [sp, #4]
e: cc0f ldmia r4!, {r0, r1, r2, r3}
10: e8ac 000f stmia.w ip!, {r0, r1, r2, r3}
14: cc0f ldmia r4!, {r0, r1, r2, r3}
16: 2d07 cmp r5, #7

Schema

The relevant portion looks like this: A table that requires an union inside, and the union has one of many tables

table MyTableResponse{
// Some integers
}
union ResponseData {
// A bunch of tables
/// Generic response (success w/ no payload or error).
MyTable: MyTableResponse,
}

table Response {
data: ResponseData (required);
}

Background

I found this by Aardappel which seems to be an user on stackoverflow who is highly involved with the project:
https://stackoverflow.com/questions/24330925/does-flatbuffers-avoid-strict-aliasing-somehow

Then in theory, if you first construct a FlatBuffer and then immediately read it, it could optimize across the writing and reading code, and do "evil" optimisations of the kind Linus was referring to in your link above (pretend the writing never happened).

Workarounds

  • Add a compiler barrier
  • Make things volatile and cast them before passing them into flatcc API's
  • Use lower optimization levels
  • Use -fno-strict-aliasing
  • A bunch of other potential compiler tricks

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