Konstantin8105 / c4go

Transpiling C code to Go code
MIT License
365 stars 38 forks source link

Failure at Converting Boolean Expression to Integer in Struct Initialization #516

Open Yeaseen opened 3 months ago

Yeaseen commented 3 months ago

Source C code

#include <stdio.h>
typedef struct{
  int intM;
} mystruct;
mystruct test_bool(int inp){
  return (mystruct){.intM = inp != 0};
}
int main(){
  int b = 5;
  mystruct result = test_bool(b);
  printf("The value of 'a' in the returned struct is: %d\n", result.intM);
  b = 0;
  result = test_bool(b);
  printf("The value of 'a' in the returned struct when b = 0 is: %d\n", result.intM);
  return 0;
}

C code's output

Screenshot 2024-08-24 at 2 57 59 AM

Translated Go code by c4go

//
//  Package - transpiled by c4go
//
//  If you have found any issues, please raise an issue at:
//  https://github.com/Konstantin8105/c4go/
//

package main

import "github.com/Konstantin8105/c4go/noarch"

// _struct_at_mnt_bigdata_YEASEEN_FuzzTranspilers_main_fuzzers_TFuzz_pre_post_works_c4go_transpile_runner_c_2 - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:2
type _struct_at_mnt_bigdata_YEASEEN_FuzzTranspilers_main_fuzzers_TFuzz_pre_post_works_c4go_transpile_runner_c_2 struct {
    intM int32
}

// mystruct - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:2
type mystruct = _struct_at_mnt_bigdata_YEASEEN_FuzzTranspilers_main_fuzzers_TFuzz_pre_post_works_c4go_transpile_runner_c_2

// test_bool - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:5
func test_bool(inp int32) mystruct {
    return mystruct{inp != 0}
}

// main - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:8
func main() {
    var b int32 = 5
    var result mystruct = test_bool(b)
    noarch.Printf([]byte("The value of 'a' in the returned struct is: %d\n\x00"), result.intM)
    b = 0
    result = test_bool(b)
    noarch.Printf([]byte("The value of 'a' in the returned struct when b = 0 is: %d\n\x00"), result.intM)
    return
}

Go compiler build error

Screenshot 2024-08-24 at 3 01 38 AM

Root Cause

c4go fails to convert boolean expression to Integer in Struct initialization

Modified Go code that works

I modified the initialization so that it could use noarch.BoolToInt function. And it gives the outputs as the source C code does.

Instead of return mystruct{inp != 0}, my modification is return mystruct{noarch.BoolToInt(inp != 0)}

//
//  Package - transpiled by c4go
//
//  If you have found any issues, please raise an issue at:
//  https://github.com/Konstantin8105/c4go/
//

package main

import "github.com/Konstantin8105/c4go/noarch"

// _struct_at_mnt_bigdata_YEASEEN_FuzzTranspilers_main_fuzzers_TFuzz_pre_post_works_c4go_transpile_runner_c_2 - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:2
type _struct_at_mnt_bigdata_YEASEEN_FuzzTranspilers_main_fuzzers_TFuzz_pre_post_works_c4go_transpile_runner_c_2 struct {
    intM int32
}

// mystruct - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:2
type mystruct = _struct_at_mnt_bigdata_YEASEEN_FuzzTranspilers_main_fuzzers_TFuzz_pre_post_works_c4go_transpile_runner_c_2

// test_bool - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:5
func test_bool(inp int32) mystruct {
    return mystruct{noarch.BoolToInt(inp != 0)}
}

// main - transpiled function from  /mnt/bigdata/YEASEEN/FuzzTranspilers-main/fuzzers/TFuzz/pre_post_works/c4go_transpile/runner.c:8
func main() {
    var b int32 = 5
    var result mystruct = test_bool(b)
    noarch.Printf([]byte("The value of 'a' in the returned struct is: %d\n\x00"), result.intM)
    b = 0
    result = test_bool(b)
    noarch.Printf([]byte("The value of 'a' in the returned struct when b = 0 is: %d\n\x00"), result.intM)
    return
}

Output after modification

Screenshot 2024-08-24 at 3 06 51 AM

Konstantin8105 commented 3 months ago

Thank you for example. Not every C features are implemented in C4Go, because (I hope) it is not popular programming writing approach:

mystruct test_bool(int inp){
  return (mystruct){.intM = inp != 0};
}
Yeaseen commented 3 months ago

The legacy C codebase includes this feature. However, if a transpiler like c4go is used to translate the C code to Go, it will fail. After all, this is the task of a transpiler to convert legacy code to memory-safe modern languages