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

Wrong handling of i1 in visitCastInst #108

Closed
ercoppa opened this issue Oct 25, 2022 · 2 comments
Closed

Wrong handling of i1 in visitCastInst #108

ercoppa opened this issue Oct 25, 2022 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@ercoppa
Copy link
Contributor

ercoppa commented Oct 25, 2022

Consider this example (inspired by a real-world code):

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int bar(unsigned char a) {
  if (a == 0xCA) return -1;
  else return 0;
}

int main() {
  unsigned char input = 0;
  read(0, &input, sizeof(input));
  int r = bar(input);
  if (r == -1) printf("Bingo!\n");
  else printf("Ok\n");
  return r;
}

Clang for bar will emit with -O1 (when using -O2, the function bar is inlined, hiding the bug):

define dso_local i32 @bar(i8 zeroext %0) local_unnamed_addr #0 {
  %2 = icmp eq i8 %0, -54
  %3 = sext i1 %2 to i32
  ret i32 %3
}

Notice the sext operation. When instrumenting with SymCC, we get:

define dso_local i32 @bar(i8 zeroext %0) local_unnamed_addr #0 {
  call void @_sym_notify_basic_block(i64 18040285541467748) #5
  %2 = call i8* @_sym_get_parameter_expression(i8 0) #5
  %3 = icmp eq i8* %2, null
  br i1 %3, label %7, label %4

4:                                                ; preds = %1
  %5 = call i8* @_sym_build_integer(i64 202, i8 8) #5
  %6 = call i8* @_sym_build_equal(i8* nonnull %2, i8* nonnull %5) #5
  br label %7

7:                                                ; preds = %1, %4
  %8 = phi i8* [ null, %1 ], [ %6, %4 ]
  %9 = icmp eq i8 %0, -54
  %10 = icmp eq i8* %8, null
  br i1 %10, label %13, label %11

11:                                               ; preds = %7
  %12 = call i8* @_sym_build_bool_to_bits(i8* nonnull %8, i8 32) #5
  br label %13

13:                                               ; preds = %7, %11
  %14 = phi i8* [ null, %7 ], [ %12, %11 ]
  %15 = sext i1 %9 to i32
  call void @_sym_set_return_expression(i8* %14) #5
  ret i32 %15
}

The problem is that _sym_build_bool_to_bits builds an If-Then-Else like if (cond, 0x0...01, 0x0...0) which is correct only in case of a zext operation but not for a sext operation. Indeed, SymCC is not able to generate an alternative input on the example:

SYMCC_OUTPUT_DIR=`pwd`/out ./main < input.txt
This is SymCC running with the QSYM backend
Reading program input until EOF (use Ctrl+D in a terminal)...
[STAT] SMT: { "solving_time": 0, "total_time": 531 }
[STAT] SMT: { "solving_time": 285 }
[STAT] SMT: { "solving_time": 285, "total_time": 1115 }
[STAT] SMT: { "solving_time": 498 }
Ok

One possible fix could be to provide, e.g., _sym_build_bool_to_sign_bits and use it in visitCastInst for the i1 case iff the instruction is Instruction::SExt.

Let me know if you want a PR along this direction or if we should design a slightly different fix.

@sebastianpoeplau sebastianpoeplau added the bug Something isn't working label Nov 3, 2022
@sebastianpoeplau sebastianpoeplau self-assigned this Nov 3, 2022
@sebastianpoeplau
Copy link
Collaborator

Nice find! And thanks for all the debug information 😊

I'm wondering if _sym_build_bool_to_bits is doing more than necessary 🤔 How about we make it return an expression for i1 unconditionally, which we then feed to either _sym_build_sext or _sym_build_zext? The downside would be an additional call into the runtime, but since there's no branching the CPU should be able to handle it rather well. And the code would fit nicely into visitCastInst... What do you think?

Your example is a really nice candidate for the test suite too. I can add it with the fix.

ercoppa added a commit to ercoppa/symcc that referenced this issue Nov 3, 2022
ercoppa added a commit to ercoppa/symcc that referenced this issue Nov 3, 2022
@ercoppa
Copy link
Contributor Author

ercoppa commented Nov 3, 2022

I have made PR #110. Let me know it if ok :)

sebastianpoeplau pushed a commit that referenced this issue Nov 4, 2022
sebastianpoeplau pushed a commit that referenced this issue Nov 4, 2022
domenukk added a commit to AFLplusplus/symcc that referenced this issue Nov 19, 2022
* This is a temporary fix due to std::iterator depercation.

This commit needs to be reverted once a proper fix is in place.

* symcc_fuzzing_helper: Move to clap3 (eurecom-s3#94)

* Revert "symcc_fuzzing_helper: Move to clap3 (eurecom-s3#94)" (eurecom-s3#101)

This reverts commit 88b464c.

* Add some FAQs to the Readme

* changed from structopt to clap 3 (eurecom-s3#103)

* fix for issue eurecom-s3#108

* fix for issue eurecom-s3#108

* LLVM 12 works without changes

* Add a clang-format configuration

This is just the output of "clang-format -style=llvm -dump-config".

* Add support for LLVM 13

Clang now uses the new pass manager for the optimization pipeline, so we
have to do the same to make Clang use our pass. Moreover, FileCheck now
complains if a configured prefix doesn't appear in the checked file; added
"ANY" in three tests where it was missing. Finally, printing
arbitrary-precision integers in QSYM needed some changes.

* Add support for LLVM 14

* LLVM 15 works without changes

* fix issue eurecom-s3#109

* Run clang-format

We should really automate this...

* Add a GitHub action that checks LLVM compatibility

* Prevent test failures in case of reordered solver output

Z3 doesn't always output model constants in the same order; make sure
that our tests don't depend on it.

* Accept symbolic input from memory

This commit adds the option to mark symbolic input by calling
symcc_make_symbolic from the program under test.

The refactoring that was required to add the new feature has had the
pleasant side effect that the QSYM backend now doesn't require the
entire input upfront anymore, making it much more convenient to feed
symbolic data through stdin.

* Run GitHub actions for pull requests only

No need for "push": the "pull_request" event already triggers when new
commits are pushed to the PR branch, and we expect all changes to go
through a PR.

Co-authored-by: Aurelien Francillon <aurelien.francillon@eurecom.fr>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: aurelf <aurelien@francillon.net>
Co-authored-by: Dominik Maier <dmnk@google.com>
Co-authored-by: Emilio Coppa <ercoppa@gmail.com>
Co-authored-by: Sebastian Poeplau <poeplau@adacore.com>
sebastianpoeplau added a commit to eurecom-s3/symqemu that referenced this issue Jan 17, 2023
The interface of the SymCC runtime has changed due to
eurecom-s3/symcc#108.

Fixes #19.
sebastianpoeplau added a commit to eurecom-s3/symqemu that referenced this issue Jan 17, 2023
The interface of the SymCC runtime has changed due to
eurecom-s3/symcc#108.

Fixes #19.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants