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

To test the assimp library on GraphFuzz. #19

Open
aT0ngMu opened this issue Sep 5, 2023 · 4 comments
Open

To test the assimp library on GraphFuzz. #19

aT0ngMu opened this issue Sep 5, 2023 · 4 comments

Comments

@aT0ngMu
Copy link

aT0ngMu commented Sep 5, 2023

Hi, GraphFuzz is a very effective testing library API's work!!!!
However, when I tested the assimp library on GraphFuzz, I encountered some issues.

Here are my steps:
1. git clone --depth=1 https:github.com/assimp/assimp.git
2. mkdir assimp_output
3. gfuzz doxygen --inputs ./sourceCode/assimp --output ./assimp_output
4. gfuzz schema infer ./assimp_output/xml ./assimp_output/schema.yaml
5. gfuzz gen cpp ./assimp_output/schema.yaml .

When I ran the fifth command, I received the following error message:

[!] Error while parsing: AC3DImporter()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~AC3DImporter() override
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Material()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Object()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Surface()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~AMFImporter() override
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: BaseNode(Type _mType, const std::string &name)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Bone(const std::string &name)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Camera(const std::string &name)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Light(const std::string &name)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Material(const std::string &name)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Mesh(const std::string &name)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Parser(const char *szFile, unsigned int fileFormatDefault)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ASEImporter()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: AttachmentInfo()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: AttachmentInfo(aiScene *_scene, aiNode *_attachToNode)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~B3DImporter() override
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: BVHLoader()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~BVHLoader()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~BaseImporter()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~BaseProcess()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ~BatchLoader()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Base()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ConversionData(const FileDatabase &db)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: CustomDataLayer()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: DNAParser(FileDatabase &db)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ElemBase()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: FileDatabase()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: FileOffset()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: MTFace()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: MVert()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: Object()
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ObjectCache(const FileDatabase &db)
'NoneType' object has no attribute 'base_type'
[!] Error while parsing: ObjectCache(const FileDatabase &)
'NoneType' object has no attribute 'base_type'
Traceback (most recent call last):
File "/home/server1/.local/bin/gfuzz", line 8, in
sys.exit(main())
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/cli.py", line 23, in main
options[args.mode].execute(args)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/cliopt.py", line 17, in execute
res = self._execute_fn(args)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/gen.py", line 24, in execute
OPTIONS[args.gen_mode].execute(args)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/cliopt.py", line 17, in execute
res = self._execute_fn(args)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/cpp/gen_cpp.py", line 1328, in execute
generate_harness(
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/cpp/gen_cpp.py", line 1247, in generate_harness
raw_scopes, max_num, errors = collect_scopes(schema, ignore_keywords, generate_dry)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/cpp/gen_cpp.py", line 1026, in collect_scopes
scopes.append(CPPScope.destructor_for(schema, obj))
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/cpp/gen_cpp.py", line 319, in destructor_for
return CPPScope.from_signature(schema, parent, sig, False)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/cpp/gen_cpp.py", line 337, in from_signature
scope_type = _classify(parent, sig, is_static)
File "/home/server1/.local/lib/python3.8/site-packages/gfuzz/commands/gen/cpp/gen_cpp.py", line 251, in _classify
if sig.func_name.name == obj_name and not is_static:
AttributeError: 'NoneType' object has no attribute 'func_name'

Is it due to my improper usage or some other reason? Looking forward to your assistance and your message!!!
Thanks!!

@hgarrereyn
Copy link
Owner

Hi, unfortunately the doxygen tool is still very experimental -- there are some edge cases that it does not properly handle, particularly with namespaces.

The issue with:

[!] Error while parsing: AC3DImporter()
'NoneType' object has no attribute 'base_type'

is caused by this struct definition:

struct_Assimp::AC3DImporter:
  default_destructor: true
  headers:
  - ACLoader.h
  methods:
  - AC3DImporter()
  - ~AC3DImporter() override
  - bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const
    override
  name: Assimp::AC3DImporter
  static_methods: []
  type: struct

In order to find the constructor and destructor, the gfuzz tool expects the function name to match either <struct_name> or ~<struct_name>. Since the name is defined with a namespace as Assimp::AC3DImporter, it expects the constructor to look like: Assimp::AC3DImporter()

Unfortunately C++ is complex enough that there are still a fair number of edge cases like this in graphfuzz.


In general, I wouldn't recommend trying to harness the entire API at once. Rather, the strategy I used was to use the doxygen tool to generate a helpful starting point, then I copy and pasted the structs/classes I was interested in fuzzing in a new schema.

It definitely looks like Assimp could benefit from API fuzzing. I would recommend starting with one or two core structs and try to get those working in an isolated harness. Then you can try to expand the harness with new structs.

Let me know if you run into any specific issues trying to do this!

@aT0ngMu
Copy link
Author

aT0ngMu commented Sep 8, 2023

Hi, unfortunately the doxygen tool is still very experimental -- there are some edge cases that it does not properly handle, particularly with namespaces.

The issue with:

[!] Error while parsing: AC3DImporter()
'NoneType' object has no attribute 'base_type'

is caused by this struct definition:

struct_Assimp::AC3DImporter:
  default_destructor: true
  headers:
  - ACLoader.h
  methods:
  - AC3DImporter()
  - ~AC3DImporter() override
  - bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const
    override
  name: Assimp::AC3DImporter
  static_methods: []
  type: struct

In order to find the constructor and destructor, the gfuzz tool expects the function name to match either <struct_name> or ~<struct_name>. Since the name is defined with a namespace as Assimp::AC3DImporter, it expects the constructor to look like: Assimp::AC3DImporter()

Unfortunately C++ is complex enough that there are still a fair number of edge cases like this in graphfuzz.

In general, I wouldn't recommend trying to harness the entire API at once. Rather, the strategy I used was to use the doxygen tool to generate a helpful starting point, then I copy and pasted the structs/classes I was interested in fuzzing in a new schema.

It definitely looks like Assimp could benefit from API fuzzing. I would recommend starting with one or two core structs and try to get those working in an isolated harness. Then you can try to expand the harness with new structs.

Let me know if you run into any specific issues trying to do this!

Thank you very much for your explanation!! But I'm still encountering some issues.

Here are my steps:

  1. Generate a schema.yaml for the entire source code of the assimp library.
    gfuzz doxygen --inputs ./sourceCode/assimp --output ./assimp_output
    gfuzz schema infer ./assimp_output/xml ./assimp_output/schema.yaml
    gfuzz gen cpp ./assimp_output/schema.yaml .
  2. Select some structures from schema.yaml and paste them into custom.yaml.
  3. Generate a harness for custom.yaml.
    gfuzz gen cpp ./custom.yaml .
  4. Compile and run the generated harness.
    clang++ -I ../assimp/include -I ../assimp/code/Common -I ../assimp/include/assimp fuzz_exec.cpp ../assimp/lib/libassimp.a -o fuzz_exec -lz -lgraphfuzz -lprotobuf -fsanitize=address,fuzzer
    ./fuzz_exec

The error message after running the harness is as follows:
[] Loading: schema.json
[
] GraphFuzz: loading trees from cache...
[!] No initializer tree for type: "aiScene" (type: 87)
[] After validation: total scopes: 19
[
] After validation: usable scopes: 18
[!] Schema is invalid. (Run with "--graphfuzz_ignore_invalid" to continue with usable scopes).

I looked at the source code of GraphFuzz, and it seems that if initializer or finalizer for a struct is empty, it cannot pass validation. I'm not sure how to construct schema.yaml to make initializers or finalizers valid. Do you have any better suggestions?

@hgarrereyn
Copy link
Owner

Hi, could you share your custom.yaml file? The error message No initializer tree for type: "aiScene" means that GraphFuzz could not figure out a way to construct the struct aiScene.

@aT0ngMu
Copy link
Author

aT0ngMu commented Sep 9, 2023

I'm very sorry, I forgot to upload. The compressed file contains the relevant files.
assimp_output.tar.gz

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

2 participants