Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__builtin_object_size(P->M, 1) where M is an array and the last member of a struct fails (need "-fstrict-flex-array") #55741

Open
kees opened this issue May 27, 2022 · 8 comments
Assignees
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl'

Comments

@kees
Copy link
Contributor

kees commented May 27, 2022

When bos1 is used on a member who is both an array and at the end of a structure, it fails to correctly resolve. This kind of behavior should only happen for flexible array members:

struct middle_array {
    int a;
    unsigned char c[16];
    int b;
};

struct trailing_array {
    int a;
    int b;
    unsigned char c[16];
};

struct flex_array {
    int a;
    int b;
    unsigned char c[];
};

Both "middle" and "trailing" should see that "c" is 16 bytes. Only "flex" should be "unbounded":

ok:  sizeof(*middle) == 24
ok:  sizeof(middle->c) == 16
ok:  __builtin_object_size(middle, 1) == -1
ok:  __builtin_object_size(middle->c, 1) == 16
ok:  sizeof(*flex) == 8
ok:  __builtin_object_size(flex, 1) == -1
ok:  __builtin_object_size(flex->c, 1) == -1
ok:  sizeof(*trailing) == 24
ok:  sizeof(trailing->c) == 16
ok:  __builtin_object_size(trailing, 1) == -1
WAT: __builtin_object_size(trailing->c, 1) == -1 (expected 16)

https://godbolt.org/z/s9nb4Y7q4

This is likely due to trailing all trailing arrays as historical flexible arrays, but it breaks FORTIFY_SOURCE in that any struct with a fixed size trailing array will receive no sanity checking. Please introduce something like "-fstrict-flex-array".

@kees
Copy link
Contributor Author

kees commented May 27, 2022

cc @nickdesaulniers @gwelymernans

@kees
Copy link
Contributor Author

kees commented May 31, 2022

Quoting from bug #55742 :

I think @efriedma-quic covers the reasons behind this well in general.

RE flexible arrays, yeah, clang's frontend gives up in many of those cases. The general pattern of code that it tries to allow for is:

struct string {
  size_t len;
  char data[0];
};

struct string *new_string(const char *s) {
  size_t len = strlen(s);
  struct string *str = malloc(sizeof(*str) + len);
  // <insert *str initialization code here>
  return str;
}

Which is relatively common in C. Clang originally had checks for whether the trailing member of the struct was unsized or had a length <= 1, but that broke in the face of e.g., FreeBSD's struct sockaddr, as @serge-sans-paille notes.

Right, the behavior makes some historical sense, but for code bases that have converted all the ancient "fake" flex-arrays to proper flex arrays, there needs to be a way to gain FORTIFY-style protections over structs with fixed-size trailing arrays. This is currently impossible. Adding -fstrict-flex-array to drop the old work-arounds is needed.

@llvmbot
Copy link
Member

llvmbot commented May 31, 2022

@llvm/issue-subscribers-clang-codegen

@kees
Copy link
Contributor Author

kees commented May 31, 2022

cc @gburgessiv @serge-sans-paille

@tstellar
Copy link
Collaborator

@msebor

@serge-sans-paille
Copy link
Collaborator

+1 for -fstrict-flex-array, I'll propose a patch

@serge-sans-paille serge-sans-paille self-assigned this Jun 1, 2022
@serge-sans-paille
Copy link
Collaborator

Patch proposed at https://reviews.llvm.org/D126864, @kees @gburgessiv I've added you as reviewers.

@EugeneZelenko EugeneZelenko added clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' and removed clang:codegen labels Jun 3, 2022
@llvmbot
Copy link
Member

llvmbot commented Jun 3, 2022

@llvm/issue-subscribers-clang-driver

rotateright added a commit that referenced this issue Dec 18, 2022
It's a bigger match than usual, but I have not found any
sub-patterns that reduce:
(X / DivC) + sext ((X & (SMin | (DivC - 1)) >u SMin) --> X >>s log2(DivC)

https://alive2.llvm.org/ce/z/MJzlhl

Fixes issue #55741
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl'
Projects
None yet
Development

No branches or pull requests

5 participants