{"id":13596040,"url":"https://github.com/shramos/pyc-cfg","last_synced_at":"2025-07-31T05:08:28.213Z","repository":{"id":49648594,"uuid":"119256935","full_name":"shramos/pyc-cfg","owner":"shramos","description":"Pyc-cfg is a pure python control flow graph builder for almost all Ansi C programming language.","archived":false,"fork":false,"pushed_at":"2018-01-28T12:48:08.000Z","size":60,"stargazers_count":53,"open_issues_count":0,"forks_count":13,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-30T00:41:51.852Z","etag":null,"topics":["ast","cfg","clang","control-flow-analysis","control-flow-graph","python","static-analyzer"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shramos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-28T12:38:40.000Z","updated_at":"2025-04-08T05:19:52.000Z","dependencies_parsed_at":"2022-08-29T07:01:15.122Z","dependency_job_id":null,"html_url":"https://github.com/shramos/pyc-cfg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shramos/pyc-cfg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shramos%2Fpyc-cfg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shramos%2Fpyc-cfg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shramos%2Fpyc-cfg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shramos%2Fpyc-cfg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shramos","download_url":"https://codeload.github.com/shramos/pyc-cfg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shramos%2Fpyc-cfg/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267988978,"owners_count":24177018,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","cfg","clang","control-flow-analysis","control-flow-graph","python","static-analyzer"],"created_at":"2024-08-01T16:02:05.691Z","updated_at":"2025-07-31T05:08:28.164Z","avatar_url":"https://github.com/shramos.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# pyc-cfg\n\nPyc-cfg is a pure python control flow graph builder for almost all Ansi C programming language. It works by building the CFG from the abstract syntax tree generated by [Clang](https://github.com/llvm-mirror/clang), and accessing it through its [python bindings](https://github.com/llvm-mirror/clang/tree/master/bindings/python) to libclang. I started this project back in 2015 as a way to learn more about compilers and static code analysis while studying my computer engineering career. Right now the code is being improved to be more pythonic and better comply with style rules, although there are some complex C language constructions that have not yet been implemented, their operation is adequate. I will be more than grateful to respond to any error report or problem you may encounter.\n\n### What is a CFG?\nIn a few words and quoting wikipedia, \n\u003e A control flow graph (CFG) in computer science is a representation, using graph notation, of all paths that might be traversed through a program during its execution.\n\nProbably a more accurate and extensive definition can be found in the [Dragon Book](https://www.amazon.es/Compilers-Principles-Techniques-Tools-Gradiance/dp/0321547985/ref=sr_1_1?s=foreign-books\u0026ie=UTF8\u0026qid=1517056798\u0026sr=1-1\u0026keywords=compilers+principles%2C+techniques%2C+and+tools), which says the following:\n\u003e A Flow Graph is a graph representation of intermediate code. The representation is constructed as follows:  \n \u003e 1. Partition  the  intermediate  code  into basic blocks, which  are  maximal  sequences  of consecutive  three-address  instructions  with  the  properties  that:  \n\u003e a) The  flow  of  control  can  only  enter  the  basic  block  through  the  first instruction  in  the  block.  That  is,  there  are  no jumps  into the  middle of  the  block.  \n\u003e b) Control will leave the block without halting or branching, except possibly  at  the  last  instruction  in  the  block.  \n\u003e 2. The  basic  blocks  become  the  nodes  of  a flow  graph, whose  edges  indicate which  blocks  can  follow  which  other  blocks.  \n\nA Control Flow Graph can be used for many things, from the generation of source code, to the construction of a static source code analyzer.\n### What are libclang and the python bindings?\nAs its [documentation](https://clang.llvm.org/doxygen/group__CINDEX.html) says:\n\u003e Libclang: The C Interface to Clang provides a relatively small API that exposes facilities for parsing source code into an abstract syntax tree (AST), loading already-parsed ASTs, traversing the AST, associating physical source locations with elements within the AST, and other facilities that support Clang-based development tools.\n\nAnd the python bindings, as it says in [its code](https://github.com/llvm-mirror/clang/blob/master/bindings/python/clang/cindex.py):\n\u003e This module provides an interface to the Clang indexing library. It is a low-level interface to the indexing library which attempts to match the Clang API directly while also being \"pythonic\".\n# Installation\nThe installation is relatively simple and the only step that can lead to complications is locating libclang.\n```\napt-get install clang\npip install -r requirements.txt\n```\nAt this point you must locate libclang and perform a symbolic link as it appears in the lower capture. I have found libclang in two positions within the file system in Debian operating systems, depending on whether it is x64 or x86:\n* x64\n```\nln -s /usr/lib/x86_64-linux-gnu/libclang* libclang.so\n```\n* x86\n```\nln -s /usr/lib/llvm-4.0/lib/libclang* libclang.so\n```\nAfter this, you only have to indicate to the python bindings where the new symbolic link to libclang is located, to do this, you must open the **utils.py** file and modify the following line by entering the path where you have created the symbolic link:\n```\nConfig.set_library_path('/usr/lib/llvm-4.0/lib') \n```\n# Usage\n* example.c\n```\n#include \u003cstdio.h\u003e\n\nint addNumbers(int a, int b);\n\nint main()\n{\n  int n1 = 0;\n  int n2 = 1;\n  int sum;  \n  sum = addNumbers(n1, n2);\n  printf(\"sum = %d\",sum);\n  return 0;\n}\n\nint addNumbers(int a,int b)\n{\n    int result;\n    result = a+b;\n    return result;\n}\n\n```\n* cfg_builder.py\n```\nfrom utils import buildCFG\n\ncfg = buildCFG('example.c', 'addNumbers')\n\nprint \"[+] Size of the CFG:\", str(cfg.size())\nprint cfg.printer()\n```\nOutput:\n```\n[+] Size of the CFG: 2\n[B0]\nPreds (1): B1\n\n[B1]\n0: int result;\n1: RefExpr: a\n2: Implicit Cast\n3: RefExpr: b\n4: Implicit Cast\n5:  a + b\n6: RefExpr: r\n7:  result = a + b\n8: RefExpr: r\n9: Implicit Cast\n10:  return result\nPreds (1): B2\nSuccs (1): B0\n\n[B2]\nSuccs (1): B1\n\n=\u003eEntry: 2\n\u003c=Exit: 0\n```\n* cfg_builder2.py\n```\nfrom utils import buildCFG\n\ncfgs = buildCFG('example.c')\n\nfor cfg in cfgs:\n    print \"\\n[+] Function: \", cfg[0]\n    print cfg[1].printer()\n```\nOutput:\n```\n[+] Function:  main\n[B0]\nPreds (1): B1\n\n[B1]\n0: value: 0\n1:  return 0\nPreds (1): B2\nSuccs (1): B0\n\n[B2]\n0: RefExpr: s\n1:  sum = addNumbers ( n1 , n2 )\n2: RefExpr: p\n3: Implicit Cast\n4: printf\nPreds (1): B3\nSuccs (1): B1\n\n[B3]\n0: value: 0\n1: int n1;\n2: value: 1\n3: int n2;\n4: int sum;\n5: RefExpr: a\n6: Implicit Cast\n7: addNumbers\nPreds (1): B4\nSuccs (1): B2\n\n[B4]\nSuccs (1): B3\n\n=\u003eEntry: 4\n\u003c=Exit: 0\n\n\n[+] Function:  addNumbers\n[B0]\nPreds (1): B1\n\n[B1]\n0: int result;\n1: RefExpr: a\n2: Implicit Cast\n3: RefExpr: b\n4: Implicit Cast\n5:  a + b\n6: RefExpr: r\n7:  result = a + b\n8: RefExpr: r\n9: Implicit Cast\n10:  return result\nPreds (1): B2\nSuccs (1): B0\n\n[B2]\nSuccs (1): B1\n\n=\u003eEntry: 2\n\u003c=Exit: 0\n```\n# Disclaimer\nAs I said before, I started this project back in 2015 as a way to learn about source code static analysis and compilers. When I wrote this code I was an initiate in Python, therefore, both the architecture and the syntax can be improved a lot. I will invest effort in improving all those things.\nOn the other hand, you can see how I have included the main file of the clang python-bindings in the project (```clang/cindex.py```). This is because Clang is in constant development and it may be that if you have a different version of python bindings, it is not compatible. Regardless of this, you can always delete that folder and access the python-bindings without making any changes to the code by installing the package ```pip install clang```.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshramos%2Fpyc-cfg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshramos%2Fpyc-cfg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshramos%2Fpyc-cfg/lists"}