Rust-GCC / Rust-GCC/gccrs

Example of -fanalyzer with gccrs

Open
#1,407 7 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
2.9k
Forks
231
Avg merge
19h 55m
Merged PRs (30d)
67

Description

For fun, I tried running gccrs with -fanalyzer ; it seems to work; here's an example of detecting a double-free in unsafe code:

https://godbolt.org/z/3PrKTP8bs

// This doesn't seem to work yet, so let's use i8 instead...
// use std::ffi::c_void;

extern "C" {
    //fn free(p: *const c_void);
    fn free(p: *const i8);
}

fn call_free (s: *const i8) {
    unsafe {
        free (s);
    }
}

pub fn test(flag: bool, s: *const i8) {
    call_free (s);
    if (flag) {
        call_free (s);
    }
}

for which I get this output in Compiler Explorer:

<source>:8:1: warning: function is never used: 'call_free'
    8 | fn call_free (s: *const i8) {
      | ^
<source>:14:5: warning: function is never used: 'test'
   14 | pub fn test(flag: bool, s: *const i8) {
      |     ^
<source>: In function 'example::call_free':
<source>:10:9: warning: double-'free' of 's_2(D)' [CWE-415] [-Wanalyzer-double-free]
   10 |         free (s);
      |         ^
  'example::test': events 1-2
    |
    |   14 | pub fn test(flag: bool, s: *const i8) {
    |      |     ^
    |      |     |
    |      |     (1) entry to 'example::test'
    |   15 |     call_free (s);
    |      |     ~
    |      |     |
    |      |     (2) calling 'example::call_free' from 'example::test'
    |
    +--> 'example::call_free': events 3-4
           |
           |    8 | fn call_free (s: *const i8) {
           |      | ^
           |      | |
           |      | (3) entry to 'example::call_free'
           |    9 |     unsafe {
           |   10 |         free (s);
           |      |         ~
           |      |         |
           |      |         (4) first 'free' here
           |
    <------+
    |
  'example::test': events 5-8
    |
    |   15 |     call_free (s);
    |      |     ^
    |      |     |
    |      |     (5) returning to 'example::test' from 'example::call_free'
    |   16 |     if (flag) {
    |      |     ~
    |      |     |
    |      |     (6) following 'true' branch (when 'flag_5(D) != 0')...
    |   17 |         call_free (s);
    |      |         ~
    |      |         |
    |      |         (7) ...to here
    |      |         (8) passing freed pointer 's_3(D)' in call to 'example::call_free' from 'example::test'
    |
    +--> 'example::call_free': events 9-10
           |
           |    8 | fn call_free (s: *const i8) {
           |      | ^
           |      | |
           |      | (9) entry to 'example::call_free'
           |    9 |     unsafe {
           |   10 |         free (s);
           |      |         ~
           |      |         |
           |      |         (10) second 'free' here; first 'free' was at (4)
           |
ASM generation compiler returned: 0

Not sure if this is at all useful, given that both gccrs and -fanalyzer are experimental, but it was fun, and is hopefully of interest to gccrs developers.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the Compiler Explorer example linked in the issue and the reported gccrs -fanalyzer output. The issue names no repository files or tests and does not define a requested change, so the scope and a measurable definition of done would need to be established first.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.