codeql icon indicating copy to clipboard operation
codeql copied to clipboard

C path matching issue

Open foxbyte9 opened this issue 1 month ago • 1 comments

C language code

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

char buf[32];

int main(int argc, char* argv[], char* envp[]){
	if(argc<2){
		printf("./fd [输入一个参数]\n");
		return 0;
	}
	
	int fd = atoi( argv[1] ) - 0x1234;
	int len = 0;
	
	len = read(fd, buf, 32);
	
	if(!strcmp("LETMEWIN\n", buf)){
		printf("恭喜你!挑战成功!\n");
		exit(0);
	}
	
	printf("程序结束\n");
	return 0;
}

This is my rule.

/**
 * @kind path-problem
 * @problem.severity warning
 * @id getenv-to-gethostbyname
 */
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.dataflow.ExternalFlow

module ReadConfig implements DataFlow::ConfigSig{
      predicate isSource(DataFlow::Node source) {
            exists(Parameter p, ArrayExpr ae |
                p.getFunction().getName() = "main" and
                ae.getArrayBase() = p.getAnAccess() and
                source.asExpr() = ae
            )
        }

        predicate isSink(DataFlow::Node sink) {
            exists(FunctionCall fc |
                fc.getTarget().getName() = "read" and
                sink.asExpr() = fc.getArgument(0)
            )
        }

}

module ReadConfigFlow = DataFlow::Global<ReadConfig>;
import ReadConfigFlow::PathGraph

from ReadConfigFlow::PathNode source, ReadConfigFlow::PathNode sink
where ReadConfigFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "read",
  source, "input"

The source can match argv[1].

Image

The sink can also match the file descriptor (fd) of the read function.

Image

However, the rule as a whole fails to match the path.

Please help me.

foxbyte9 avatar Nov 21 '25 01:11 foxbyte9

Hi @foxbyte9 👋🏻

DataFlow::Global is used for value-preserving dataflow, in the sense that the same value should be passed unaltered from source to sink. But since you do an arithmetic operation along the flow path (atoi( argv[1] ) - 0x1234), it's not value-preserving. For that use case, there is a more general version of data flow called TaintTracking, which allows non-value-preserving operations along the path.

If you replace DataFlow::Global with TaintTracking::Global, then your query should find results.

d10c avatar Nov 21 '25 14:11 d10c