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

Segfault on OS X when providing a custom formatting function #276

Closed
vitaut opened this issue Feb 22, 2016 · 6 comments
Closed

Segfault on OS X when providing a custom formatting function #276

vitaut opened this issue Feb 22, 2016 · 6 comments

Comments

@vitaut
Copy link
Contributor

vitaut commented Feb 22, 2016

Compiling and running the following code

#include "format.h"

struct Foo {};

void format(fmt::BasicFormatter<char> &f, const char *&, Foo) {}

int main() {
  fmt::print("{}", Foo());
}

results in segfault:

$ clang++ -std=c++11 -O1 test.cc format.cc
$ ./a.out 
Segmentation fault: 11

Only occurs if optimization enabled and with -std=c++11.

@ghost
Copy link

ghost commented Feb 22, 2016

FWIW, I can't replicate the segfault using the current master (f64ea62). The example program compiled as shown does not result in a crash. I'm using Xcode 7.2.1:

> clang++ --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

@vitaut
Copy link
Contributor Author

vitaut commented Feb 22, 2016

Thanks, @LogicalKnight. Looks like this only occurs on an old Clang:

Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix

@vitaut
Copy link
Contributor Author

vitaut commented Feb 22, 2016

Narrowed it further to an invalid ArgList object:

void test(const char *, fmt::ArgList args) {
  std::printf("%p\n", args[0].custom.format);
}
FMT_VARIADIC(void, test, const char *)

struct Foo {};

void format(fmt::BasicFormatter<char> &f, const char *&, Foo) {}

int main() {
  test("", Foo());
}

Prints 0xccb0 which doesn't appear to be a valid pointer.

@vitaut
Copy link
Contributor Author

vitaut commented Feb 23, 2016

To be more specific, the problem is in fmt::internal::ArgArray::make or the way this version of clang compiles it:

  std::printf("%p\n", fmt::internal::ArgArray<1>::make<fmt::BasicFormatter<char> >(Foo()).custom.format);

prints 0xcd90 instead of 0x1065bcd90 (only the lower two bytes of custom.format are returned).

@vitaut
Copy link
Contributor Author

vitaut commented Feb 23, 2016

Clang miscompiles ArgArray::make:

__ZN3fmt8internal8ArgArrayILj1ELb1EE4makeINS_14BasicFormatterIcEE3FooEENS0_5ValueERKT0_: ## @_ZN3fmt8internal8ArgArrayILj1ELb1EE4makeINS_14BasicFormatterIcEE3FooEENS0_5ValueERKT0_
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp12:
    .cfi_def_cfa_offset 16
Ltmp13:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp14:
    .cfi_def_cfa_register %rbp
    subq    $32, %rsp
    movq    %rdi, %rax
    leaq    -32(%rbp), %rdi
    movq    %rax, %rsi
    xorl    %edx, %edx
    callq   __ZN3fmt8internal9MakeValueINS_14BasicFormatterIcEEEC1I3FooEERKT_NS0_8EnableIfIXsr3NotIXsr12ConvertToIntIS7_EE5valueEEE5valueEiE4typeE
    movq    -32(%rbp), %rax
    movzwl  -24(%rbp), %edx
    addq    $32, %rsp
    popq    %rbp
    ret
    .cfi_endproc

Note that it emits movzwl -24(%rbp), %edx to copy the custom.format pointer which only copies lower 16 bits!

@vitaut
Copy link
Contributor Author

vitaut commented Feb 23, 2016

Implemented a workaround in 209748f. The bug seems to have been fixed in newer versions of clang.

@vitaut vitaut closed this as completed Feb 23, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant