From b505447504cf3051310c7956101e3b28b1b8862c Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 09:54:44 +0200 Subject: [PATCH 01/19] Updated query pack metadata --- .codeqlmanifest.json | 4 ++-- cpp/lib/codeql-pack.lock.yml | 22 ++++++++++++++++++---- cpp/lib/{qlpack.yml => codeql-pack.yml} | 5 +++-- cpp/src/codeql-pack.lock.yml | 22 +++++++++++++++++++++- cpp/src/{qlpack.yml => codeql-pack.yml} | 0 cpp/test/codeql-pack.lock.yml | 22 +++++++++++++++++++++- cpp/test/{qlpack.yml => codeql-pack.yml} | 0 go/src/codeql-pack.lock.yml | 16 +++++++++++++++- go/src/{qlpack.yml => codeql-pack.yml} | 0 go/test/codeql-pack.lock.yml | 16 +++++++++++++++- go/test/{qlpack.yml => codeql-pack.yml} | 0 11 files changed, 95 insertions(+), 12 deletions(-) rename cpp/lib/{qlpack.yml => codeql-pack.yml} (62%) rename cpp/src/{qlpack.yml => codeql-pack.yml} (100%) rename cpp/test/{qlpack.yml => codeql-pack.yml} (100%) rename go/src/{qlpack.yml => codeql-pack.yml} (100%) rename go/test/{qlpack.yml => codeql-pack.yml} (100%) diff --git a/.codeqlmanifest.json b/.codeqlmanifest.json index 3025e97..e2f0ddc 100644 --- a/.codeqlmanifest.json +++ b/.codeqlmanifest.json @@ -1,6 +1,6 @@ { "provide": [ - "cpp/*/qlpack.yml", - "go/*/qlpack.yml" + "cpp/*/codeql-pack.yml", + "go/*/codeql-pack.yml" ] } \ No newline at end of file diff --git a/cpp/lib/codeql-pack.lock.yml b/cpp/lib/codeql-pack.lock.yml index e7600d8..6eaef3f 100644 --- a/cpp/lib/codeql-pack.lock.yml +++ b/cpp/lib/codeql-pack.lock.yml @@ -2,9 +2,23 @@ lockVersion: 1.0.0 dependencies: codeql/cpp-all: - version: 0.6.1 - codeql/ssa: + version: 0.13.0 + codeql/dataflow: + version: 0.2.6 + codeql/mad: + version: 0.2.15 + codeql/rangeanalysis: version: 0.0.14 + codeql/ssa: + version: 0.2.15 codeql/tutorial: - version: 0.0.7 -compiled: false + version: 0.2.15 + codeql/typeflow: + version: 0.0.2 + codeql/typetracking: + version: 0.2.15 + codeql/util: + version: 0.2.15 + codeql/xml: + version: 0.0.2 +compiled: false \ No newline at end of file diff --git a/cpp/lib/qlpack.yml b/cpp/lib/codeql-pack.yml similarity index 62% rename from cpp/lib/qlpack.yml rename to cpp/lib/codeql-pack.yml index e70ab5b..95caaa6 100644 --- a/cpp/lib/qlpack.yml +++ b/cpp/lib/codeql-pack.yml @@ -1,9 +1,10 @@ --- name: trailofbits/cpp-all authors: Trail of Bits -version: 0.2.1 license: AGPL +version: 1.0.0 library: true extractor: cpp +warnOnImplicitThis: false dependencies: - codeql/cpp-all: "*" + codeql/cpp-all: ^0.13.0 \ No newline at end of file diff --git a/cpp/src/codeql-pack.lock.yml b/cpp/src/codeql-pack.lock.yml index 5300427..1e5b635 100644 --- a/cpp/src/codeql-pack.lock.yml +++ b/cpp/src/codeql-pack.lock.yml @@ -1,4 +1,24 @@ --- lockVersion: 1.0.0 -dependencies: {} +dependencies: + codeql/cpp-all: + version: 0.13.0 + codeql/dataflow: + version: 0.2.6 + codeql/mad: + version: 0.2.15 + codeql/rangeanalysis: + version: 0.0.14 + codeql/ssa: + version: 0.2.15 + codeql/tutorial: + version: 0.2.15 + codeql/typeflow: + version: 0.0.2 + codeql/typetracking: + version: 0.2.15 + codeql/util: + version: 0.2.15 + codeql/xml: + version: 0.0.2 compiled: false diff --git a/cpp/src/qlpack.yml b/cpp/src/codeql-pack.yml similarity index 100% rename from cpp/src/qlpack.yml rename to cpp/src/codeql-pack.yml diff --git a/cpp/test/codeql-pack.lock.yml b/cpp/test/codeql-pack.lock.yml index 5300427..1e5b635 100644 --- a/cpp/test/codeql-pack.lock.yml +++ b/cpp/test/codeql-pack.lock.yml @@ -1,4 +1,24 @@ --- lockVersion: 1.0.0 -dependencies: {} +dependencies: + codeql/cpp-all: + version: 0.13.0 + codeql/dataflow: + version: 0.2.6 + codeql/mad: + version: 0.2.15 + codeql/rangeanalysis: + version: 0.0.14 + codeql/ssa: + version: 0.2.15 + codeql/tutorial: + version: 0.2.15 + codeql/typeflow: + version: 0.0.2 + codeql/typetracking: + version: 0.2.15 + codeql/util: + version: 0.2.15 + codeql/xml: + version: 0.0.2 compiled: false diff --git a/cpp/test/qlpack.yml b/cpp/test/codeql-pack.yml similarity index 100% rename from cpp/test/qlpack.yml rename to cpp/test/codeql-pack.yml diff --git a/go/src/codeql-pack.lock.yml b/go/src/codeql-pack.lock.yml index 5300427..6f38945 100644 --- a/go/src/codeql-pack.lock.yml +++ b/go/src/codeql-pack.lock.yml @@ -1,4 +1,18 @@ --- lockVersion: 1.0.0 -dependencies: {} +dependencies: + codeql/dataflow: + version: 0.2.6 + codeql/go-all: + version: 0.8.0 + codeql/mad: + version: 0.2.15 + codeql/ssa: + version: 0.2.15 + codeql/tutorial: + version: 0.2.15 + codeql/typetracking: + version: 0.2.15 + codeql/util: + version: 0.2.15 compiled: false diff --git a/go/src/qlpack.yml b/go/src/codeql-pack.yml similarity index 100% rename from go/src/qlpack.yml rename to go/src/codeql-pack.yml diff --git a/go/test/codeql-pack.lock.yml b/go/test/codeql-pack.lock.yml index 5300427..6f38945 100644 --- a/go/test/codeql-pack.lock.yml +++ b/go/test/codeql-pack.lock.yml @@ -1,4 +1,18 @@ --- lockVersion: 1.0.0 -dependencies: {} +dependencies: + codeql/dataflow: + version: 0.2.6 + codeql/go-all: + version: 0.8.0 + codeql/mad: + version: 0.2.15 + codeql/ssa: + version: 0.2.15 + codeql/tutorial: + version: 0.2.15 + codeql/typetracking: + version: 0.2.15 + codeql/util: + version: 0.2.15 compiled: false diff --git a/go/test/qlpack.yml b/go/test/codeql-pack.yml similarity index 100% rename from go/test/qlpack.yml rename to go/test/codeql-pack.yml From 454f15c9793126afb982477484801a2367301a90 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 09:57:29 +0200 Subject: [PATCH 02/19] Added initial support for GGML --- cpp/lib/trailofbits/crypto/common.qll | 24 ++-- cpp/lib/trailofbits/ml/common.qll | 2 + .../trailofbits/ml/common/CustomAllocator.qll | 123 ++++++++++++++++++ cpp/lib/trailofbits/ml/common/ReturnValue.qll | 88 +++++++++++++ cpp/lib/trailofbits/ml/ggml.qll | 1 + cpp/lib/trailofbits/ml/ggml/ggml.qll | 32 +++++ cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll | 68 ++++++++++ cpp/lib/trailofbits/ml/libraries.qll | 1 + cpp/src/codeql-suites/tob-cpp-ml.qls | 5 + cpp/src/ml/LocalMemoryLeak.ql | 33 +++++ cpp/src/ml/LocalUseAfterFree.ql | 33 +++++ cpp/src/ml/ReturnValueNotChecked.ql | 22 ++++ cpp/src/ml/ReturnValueNotUsed.ql | 21 +++ cpp/test/include/ggml/ggml-alloc.h | 18 +++ cpp/test/include/ggml/ggml.h | 1 + .../CustomAllocator/CustomAllocator.expected | 5 + .../ml/CustomAllocator/CustomAllocator.ql | 23 ++++ .../library-tests/ml/CustomAllocator/test.c | 39 ++++++ .../LocalMemoryLeak/LocalMemoryLeak.expected | 1 + .../ml/LocalMemoryLeak/LocalMemoryLeak.qlref | 1 + .../query-tests/ml/LocalMemoryLeak/test.c | 39 ++++++ .../LocalUseAfterFree.expected | 2 + .../LocalUseAfterFree/LocalUseAfterFree.qlref | 1 + .../query-tests/ml/LocalUseAfterFree/test.c | 63 +++++++++ .../ReturnValueNotUsed.expected | 1 + .../ReturnValueNotUsed.qlref | 1 + .../query-tests/ml/ReturnValueNotUsed/test.c | 27 ++++ 27 files changed, 663 insertions(+), 12 deletions(-) create mode 100644 cpp/lib/trailofbits/ml/common.qll create mode 100644 cpp/lib/trailofbits/ml/common/CustomAllocator.qll create mode 100644 cpp/lib/trailofbits/ml/common/ReturnValue.qll create mode 100644 cpp/lib/trailofbits/ml/ggml.qll create mode 100644 cpp/lib/trailofbits/ml/ggml/ggml.qll create mode 100644 cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll create mode 100644 cpp/lib/trailofbits/ml/libraries.qll create mode 100644 cpp/src/codeql-suites/tob-cpp-ml.qls create mode 100644 cpp/src/ml/LocalMemoryLeak.ql create mode 100644 cpp/src/ml/LocalUseAfterFree.ql create mode 100644 cpp/src/ml/ReturnValueNotChecked.ql create mode 100644 cpp/src/ml/ReturnValueNotUsed.ql create mode 100644 cpp/test/include/ggml/ggml-alloc.h create mode 100644 cpp/test/include/ggml/ggml.h create mode 100644 cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected create mode 100644 cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql create mode 100644 cpp/test/library-tests/ml/CustomAllocator/test.c create mode 100644 cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected create mode 100644 cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.qlref create mode 100644 cpp/test/query-tests/ml/LocalMemoryLeak/test.c create mode 100644 cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected create mode 100644 cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.qlref create mode 100644 cpp/test/query-tests/ml/LocalUseAfterFree/test.c create mode 100644 cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.expected create mode 100644 cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.qlref create mode 100644 cpp/test/query-tests/ml/ReturnValueNotUsed/test.c diff --git a/cpp/lib/trailofbits/crypto/common.qll b/cpp/lib/trailofbits/crypto/common.qll index 335c075..775d376 100644 --- a/cpp/lib/trailofbits/crypto/common.qll +++ b/cpp/lib/trailofbits/crypto/common.qll @@ -1,13 +1,13 @@ -import common.InitUpdateFinalPattern -import common.SymmetricCipherContext +import trailofbits.crypto.common.InitUpdateFinalPattern +import trailofbits.crypto.common.SymmetricCipherContext -import common.Csprng -import common.ErrorCode -import common.HashFunction -import common.CustomAllocator -import common.CsprngInitializer -import common.StrongPasswordSink -import common.StrongRandomnessSink -import common.WeakRandomnessSource -import common.StaticCryptoVariable -import common.KeyDerivationFunction +import trailofbits.crypto.common.Csprng +import trailofbits.crypto.common.ErrorCode +import trailofbits.crypto.common.HashFunction +import trailofbits.crypto.common.CustomAllocator +import trailofbits.crypto.common.CsprngInitializer +import trailofbits.crypto.common.StrongPasswordSink +import trailofbits.crypto.common.StrongRandomnessSink +import trailofbits.crypto.common.WeakRandomnessSource +import trailofbits.crypto.common.StaticCryptoVariable +import trailofbits.crypto.common.KeyDerivationFunction diff --git a/cpp/lib/trailofbits/ml/common.qll b/cpp/lib/trailofbits/ml/common.qll new file mode 100644 index 0000000..0b145ed --- /dev/null +++ b/cpp/lib/trailofbits/ml/common.qll @@ -0,0 +1,2 @@ +import common.CustomAllocator +import common.ReturnValue \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll b/cpp/lib/trailofbits/ml/common/CustomAllocator.qll new file mode 100644 index 0000000..28dbdbe --- /dev/null +++ b/cpp/lib/trailofbits/ml/common/CustomAllocator.qll @@ -0,0 +1,123 @@ +import cpp +import ReturnValue + +private import semmle.code.cpp.dataflow.new.DataFlow +private import semmle.code.cpp.controlflow.StackVariableReachability + +/** + * A custom `alloc` function which returns a pointer to the allocated memory. + */ +abstract class Alloc extends MustCheck {} + +/** + * A custom `free` which takes a pointer to the allocated memory as its only + * argument. + */ +abstract class Free extends Function {} + +/** + * A custom allocator is a pair of functions `(alloc, free)`. We assume that + * `alloc` returns a pointer to the allocated memory, and that `free` takes + * a pointer to the allocated memory as its only argument. + */ +abstract class CustomAllocator extends string { + + bindingset[this] + CustomAllocator() { any() } + + /** + * Is true if `f` is an `alloc` function for the custom allocator. (There + * may be more than one function that serves as an `alloc` function for the + * allocator.) + * + * If the `alloc` function takes the allocated pointer as an argument, override + * `isAllocatedBy` directly instead. + */ + abstract predicate isAlloc(Function f); + + /** + * Is true if `f` is a `free` function for the custom allocator. (There + * may be more than one function that serves as a `free` function for the + * allocator.) + * + * If the `free` function takes more than one argument, override `isFreedBy` + * directly instead. + */ + abstract predicate isFree(Function f); + + /** + * Returns a call to an `alloc` function. + */ + FunctionCall getAnAllocCall() { + this.isAlloc(result.getTarget()) + } + + /** + * Returns a call to a `free` function. + */ + FunctionCall getAFreeCall() { + this.isFree(result.getTarget()) + } + + /** + * True if `var` is allocated by the `alloc` call. + */ + predicate isAllocatedBy(FunctionCall alloc, Variable var) { + alloc = this.getAnAllocCall() and alloc = var.getAnAssignedValue() + } + + /** + * True if `var` is freed by the `free` call. + */ + predicate isFreedBy(FunctionCall free, Variable var) { + free = this.getAFreeCall() and free.getAnArgument() = var.getAnAccess() + } +} + +class LocalMemoryLeak extends StackVariableReachabilityWithReassignment { + CustomAllocator alloc; + + LocalMemoryLeak() { + this = "LocalMemoryLeak" + } + + override predicate isSourceActual(ControlFlowNode node, StackVariable var) { + alloc.isAllocatedBy(node, var) + } + + override predicate isBarrier(ControlFlowNode node, StackVariable var) { + alloc.isFreedBy(node, var) + } + + override predicate isSinkActual(ControlFlowNode node, StackVariable var) { + // A sink is a return statement not returning the allocated variable. + node instanceof ReturnStmt and not node.(ReturnStmt).getExpr() = var.getAnAccess() + } + } + + class LocalUseAfterFree extends StackVariableReachabilityWithReassignment { + CustomAllocator alloc; + + LocalUseAfterFree() { + this = "LocalUseAfterFree" + } + + override predicate isSourceActual(ControlFlowNode node, StackVariable var) { + alloc.isFreedBy(node, var) + } + + override predicate isSinkActual(ControlFlowNode node, StackVariable var) { + // A sink is an access which is not a reassignment. + node = var.getAnAccess() and not this.isAnAssignment(node, var) + } + + override predicate isBarrier(ControlFlowNode node, StackVariable var) { + // Stop tracking the variable if it is reassigned. + this.isAnAssignment(node, var) + } + + // Returns true if the `node` is the lvalue of an assignment to `var`. + predicate isAnAssignment(ControlFlowNode node, StackVariable var) { + node = var.getAnAssignment().getLValue() + } + } \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/common/ReturnValue.qll b/cpp/lib/trailofbits/ml/common/ReturnValue.qll new file mode 100644 index 0000000..cef6719 --- /dev/null +++ b/cpp/lib/trailofbits/ml/common/ReturnValue.qll @@ -0,0 +1,88 @@ +import cpp + +import semmle.code.cpp.dataflow.new.DataFlow + +/** + * Identifies functions where the return value must be used in some way. + */ +abstract class MustUse extends Function { } + +/** + * Identifies functions where the return value must be checked. + */ +abstract class MustCheck extends Function { } + +/** + * The return value of a function. + */ +class ReturnValue extends FunctionCall { + /** + * Returns the function that the return value corresponds to. + */ + Function getFunction() { + result = this.getTarget() + } + /** + * True if the return value must be used. + */ + predicate mustUse() { + this.getTarget() instanceof MustUse + } + + /** + * True if the return value must be used. + */ + predicate mustCheck() { + this.getTarget() instanceof MustCheck + } + + /** + * Returns true if the corresponding function call is not an expression + * statement. + */ + predicate isUsed() { + not exists(ExprStmt stmt | this = stmt.getExpr()) + } + + /** + * Returns true if the return value flows into a conditional statement or + * expression, or a return statement. + */ + predicate isChecked() { + // The return value flows into the condition of an if-statement. + exists (IfStmt is | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(is.getCondition().getAChild*()) + ) + ) or + // The return value flows into the condition of a while-statement. + exists (WhileStmt ws | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(ws.getCondition().getAChild*()) + ) + ) or + // The return value flows into the condition of a switch-statement. + exists (SwitchStmt ss | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(ss.getExpr().getAChild*()) + ) + ) or + // The return value flows into a conditional expression. + exists (ConditionalExpr ce | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(ce.getCondition().getAChild*()) + ) + ) or + // The return value is returned by the function. + exists (ReturnStmt rs | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(rs.getExpr().getAChild*()) + ) + ) + } +} diff --git a/cpp/lib/trailofbits/ml/ggml.qll b/cpp/lib/trailofbits/ml/ggml.qll new file mode 100644 index 0000000..48b0f2a --- /dev/null +++ b/cpp/lib/trailofbits/ml/ggml.qll @@ -0,0 +1 @@ +import ggml.ggml_alloc diff --git a/cpp/lib/trailofbits/ml/ggml/ggml.qll b/cpp/lib/trailofbits/ml/ggml/ggml.qll new file mode 100644 index 0000000..339ec1b --- /dev/null +++ b/cpp/lib/trailofbits/ml/ggml/ggml.qll @@ -0,0 +1,32 @@ +import trailofbits.ml.common + +/** + * struct ggml_context * ggml_init(struct ggml_init_params params); + */ +class GGML_init extends Alloc { + GGML_init() { + this.getName() = "ggml_init" + } +} + +/** + * void ggml_free(struct ggml_context * ctx); + */ +class GGML_free extends Free { + GGML_free() { + this.getName() = "ggml_free" + } +} + +class ContextAllocator extends CustomAllocator { + ContextAllocator() { + this = "ContextAllocator" + } + override predicate isAlloc(Function f) { + f instanceof GGML_init + } + + override predicate isFree(Function f) { + f instanceof GGML_free + } +} \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll new file mode 100644 index 0000000..078633a --- /dev/null +++ b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll @@ -0,0 +1,68 @@ +import trailofbits.ml.common + +/** + * GGML_API ggml_gallocr_t ggml_gallocr_new(ggml_backend_buffer_type_t buft); + * + * The allocator guarantees that the return value and internal fields are not NULL. + */ +class GGML_gallocr_new extends Alloc { + GGML_gallocr_new() { this.getName() = "ggml_gallocr_new" } +} + +/** + * GGML_API ggml_gallocr_t ggml_gallocr_new_n(ggml_backend_buffer_type_t * bufts, int n_bufs); + */ +class GGML_gallocr_new_n extends Alloc { + GGML_gallocr_new_n() { this.getName() = "ggml_gallocr_new_n" } +} + +/** + * GGML_API void ggml_gallocr_free(ggml_gallocr_t galloc); + */ +class GGML_gallocr_free extends Free { + GGML_gallocr_free() { this.getName() = "ggml_gallocr_free" } +} + +/** + * GGML_API bool ggml_gallocr_alloc_graph(ggml_gallocr_t galloc, struct ggml_cgraph * graph); + */ +class GGML_gallocr_alloc_graph extends MustCheck { + GGML_gallocr_alloc_graph() { this.getName() = "ggml_gallocr_alloc_graph" } +} + +/** + * GGML_API bool ggml_gallocr_reserve(ggml_gallocr_t galloc, struct ggml_cgraph * graph); + */ +class GGML_gallocr_reserve extends MustCheck { + GGML_gallocr_reserve() { this.getName() = "ggml_gallocr_reserve" } +} + +/** + * GGML_API bool ggml_gallocr_reserve_n( + * ggml_gallocr_t galloc, + * struct ggml_cgraph * graph, + * const int * node_buffer_ids, + * const int * leaf_buffer_ids); + */ +class GGML_gallocr_reserve_n extends MustCheck { + GGML_gallocr_reserve_n() { this.getName() = "ggml_gallocr_reserve_n" } +} + +/** + * GGML_API size_t ggml_gallocr_get_buffer_size(ggml_gallocr_t galloc, int buffer_id); + */ +class GGML_gallocr_get_buffer_size extends MustUse { + GGML_gallocr_get_buffer_size() { this.getName() = "ggml_gallocr_get_buffer_size" } +} + +class GraphAllocator extends CustomAllocator { + GraphAllocator() { this = "GraphAllocator" } + + override predicate isAlloc(Function f) { + (f instanceof GGML_gallocr_new) or (f instanceof GGML_gallocr_new_n) + } + + override predicate isFree(Function f) { + f instanceof GGML_gallocr_free + } +} \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/libraries.qll b/cpp/lib/trailofbits/ml/libraries.qll new file mode 100644 index 0000000..1136473 --- /dev/null +++ b/cpp/lib/trailofbits/ml/libraries.qll @@ -0,0 +1 @@ +import ggml \ No newline at end of file diff --git a/cpp/src/codeql-suites/tob-cpp-ml.qls b/cpp/src/codeql-suites/tob-cpp-ml.qls new file mode 100644 index 0000000..1dc40fa --- /dev/null +++ b/cpp/src/codeql-suites/tob-cpp-ml.qls @@ -0,0 +1,5 @@ +- description: ML queries for C and C++ +- queries: 'ml' + from: trailofbits/cpp-queries +- exclude: + tags contain: experimental \ No newline at end of file diff --git a/cpp/src/ml/LocalMemoryLeak.ql b/cpp/src/ml/LocalMemoryLeak.ql new file mode 100644 index 0000000..4a95dd8 --- /dev/null +++ b/cpp/src/ml/LocalMemoryLeak.ql @@ -0,0 +1,33 @@ +/** + * @name Memory leak related to custom allocator + * @id tob/cpp/local-memory-leak + * @description Finds memory leaks related to GGML custom allocators + * @kind problem + * @tags correctness ml + * @problem.severity warning + * @precision medium + * @group ml + */ + +import cpp +import trailofbits.ml.common +import trailofbits.ml.libraries + +string toLine(ControlFlowNode node) { result = node.getLocation().getStartLine().toString() } + +string toMessage(ControlFlowNode source, ControlFlowNode sink, StackVariable var) { + result = + "The variable `" + var + "` is allocated on line " + + toLine(source) + " and leaks on line " + toLine(sink) + +} + +from + LocalMemoryLeak leak, + ControlFlowNode source, + ControlFlowNode sink, + StackVariable var +where + leak.reaches(source, var, sink) +select + source.getLocation(), toMessage(source, sink, var) \ No newline at end of file diff --git a/cpp/src/ml/LocalUseAfterFree.ql b/cpp/src/ml/LocalUseAfterFree.ql new file mode 100644 index 0000000..423d83c --- /dev/null +++ b/cpp/src/ml/LocalUseAfterFree.ql @@ -0,0 +1,33 @@ +/** + * @name Use after free related to custom allocator + * @id tob/cpp/local-use-after-free + * @description Finds use-after-frees related to GGML custom allocators + * @kind problem + * @tags correctness ml + * @problem.severity warning + * @precision medium + * @group ml + */ + +import cpp +import trailofbits.ml.common +import trailofbits.ml.libraries + +string toLine(ControlFlowNode node) { result = node.getLocation().getStartLine().toString() } + +string toMessage(ControlFlowNode source, ControlFlowNode sink, StackVariable var) { + result = + "The variable `" + var + "` is deallocated on line " + + toLine(source) + " and subsequently used on line " + toLine(sink) + +} + +from + LocalUseAfterFree uaf, + ControlFlowNode source, + ControlFlowNode sink, + StackVariable var +where + uaf.reaches(source, var, sink) +select + sink.getLocation(), toMessage(source, sink, var) \ No newline at end of file diff --git a/cpp/src/ml/ReturnValueNotChecked.ql b/cpp/src/ml/ReturnValueNotChecked.ql new file mode 100644 index 0000000..e9a6a1c --- /dev/null +++ b/cpp/src/ml/ReturnValueNotChecked.ql @@ -0,0 +1,22 @@ +/** + * @name Function return value is discarded + * @id tob/cpp/return-value-not-checked + * @description Finds function calls where the return value is expected to be used + * @kind problem + * @tags correctness ml + * @problem.severity warning + * @precision medium + * @group ml + */ + +import cpp +import trailofbits.ml.common +import trailofbits.ml.libraries + + +from + ReturnValue value +where + value.mustCheck() and not value.isChecked() +select + value.getLocation(), "The return value of `" + value.getFunction() + "` is not checked" \ No newline at end of file diff --git a/cpp/src/ml/ReturnValueNotUsed.ql b/cpp/src/ml/ReturnValueNotUsed.ql new file mode 100644 index 0000000..6f9f9fb --- /dev/null +++ b/cpp/src/ml/ReturnValueNotUsed.ql @@ -0,0 +1,21 @@ +/** + * @name Function return value is discarded + * @id tob/cpp/return-value-not-used + * @description Finds function calls where the return value is expected to be used + * @kind problem + * @tags correctness ml + * @problem.severity warning + * @precision medium + * @group ml + */ + +import cpp +import trailofbits.ml.common +import trailofbits.ml.libraries + +from + ReturnValue value +where + value.mustUse() and not value.isUsed() +select + value.getLocation(), "The return value of `" + value.getFunction() + "` is discarded here" \ No newline at end of file diff --git a/cpp/test/include/ggml/ggml-alloc.h b/cpp/test/include/ggml/ggml-alloc.h new file mode 100644 index 0000000..1d8e6c9 --- /dev/null +++ b/cpp/test/include/ggml/ggml-alloc.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ggml.h" + +typedef void* ggml_backend_buffer_type_t; +typedef void* ggml_gallocr_t; + +ggml_gallocr_t ggml_gallocr_new(ggml_backend_buffer_type_t buft) { return 0; } +ggml_gallocr_t ggml_gallocr_new_n(ggml_backend_buffer_type_t * bufts, int n_bufs) { return 0; } +void ggml_gallocr_free(ggml_gallocr_t galloc) {} + +# ifdef __cplusplus +} +#endif diff --git a/cpp/test/include/ggml/ggml.h b/cpp/test/include/ggml/ggml.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/cpp/test/include/ggml/ggml.h @@ -0,0 +1 @@ +#pragma once diff --git a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected b/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected new file mode 100644 index 0000000..b547a08 --- /dev/null +++ b/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected @@ -0,0 +1,5 @@ +| 8 | `graph` is allocated here | +| 16 | `graph` is freed here | +| 22 | `graph` is allocated here | +| 33 | `graph` is freed here | +| 35 | `graph` is freed here | diff --git a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql b/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql new file mode 100644 index 0000000..bcedf80 --- /dev/null +++ b/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql @@ -0,0 +1,23 @@ +import cpp +import trailofbits.ml.common +import trailofbits.ml.libraries + +from + CustomAllocator allocator, + StackVariable var, + ControlFlowNode node, + string message, + int line +where + ( + allocator.isAllocatedBy(node, var) and + message = "`" + var + "` is allocated here" and + line = node.getLocation().getStartLine() + ) or + ( + allocator.isFreedBy(node, var) and + message = "`" + var + "` is freed here" and + line = node.getLocation().getStartLine() + ) +select + line, message \ No newline at end of file diff --git a/cpp/test/library-tests/ml/CustomAllocator/test.c b/cpp/test/library-tests/ml/CustomAllocator/test.c new file mode 100644 index 0000000..0ff12e1 --- /dev/null +++ b/cpp/test/library-tests/ml/CustomAllocator/test.c @@ -0,0 +1,39 @@ +#include "../../../include/ggml/ggml-alloc.h" + +int condition(int flag) { + return (flag == 1); +} + +int bad(int flag) { + ggml_gallocr_t graph = ggml_gallocr_new(0); + + if (condition(flag)) { + // `graph` may leak here. + return -1; + } + + // `graph` is properly freed here. + ggml_gallocr_free(graph); + return 0; +} + + +ggml_gallocr_t good() { + ggml_gallocr_t graph = ggml_gallocr_new(0); + return graph; +} + +int main(int argc, char** argv) { + int flag = 0; + + ggml_gallocr_t graph = good(); + bad(flag); + + if (condition(flag)) { + ggml_gallocr_free(graph); + } else { + ggml_gallocr_free(graph); + } + + return 0; +} diff --git a/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected b/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected new file mode 100644 index 0000000..0452183 --- /dev/null +++ b/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected @@ -0,0 +1 @@ +| test.c:8:26:8:41 | test.c:8:26:8:41 | The variable `graph` is allocated on line 8 and leaks on line 12 | diff --git a/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.qlref b/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.qlref new file mode 100644 index 0000000..a587df2 --- /dev/null +++ b/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.qlref @@ -0,0 +1 @@ +ml/LocalMemoryLeak.ql \ No newline at end of file diff --git a/cpp/test/query-tests/ml/LocalMemoryLeak/test.c b/cpp/test/query-tests/ml/LocalMemoryLeak/test.c new file mode 100644 index 0000000..0ff12e1 --- /dev/null +++ b/cpp/test/query-tests/ml/LocalMemoryLeak/test.c @@ -0,0 +1,39 @@ +#include "../../../include/ggml/ggml-alloc.h" + +int condition(int flag) { + return (flag == 1); +} + +int bad(int flag) { + ggml_gallocr_t graph = ggml_gallocr_new(0); + + if (condition(flag)) { + // `graph` may leak here. + return -1; + } + + // `graph` is properly freed here. + ggml_gallocr_free(graph); + return 0; +} + + +ggml_gallocr_t good() { + ggml_gallocr_t graph = ggml_gallocr_new(0); + return graph; +} + +int main(int argc, char** argv) { + int flag = 0; + + ggml_gallocr_t graph = good(); + bad(flag); + + if (condition(flag)) { + ggml_gallocr_free(graph); + } else { + ggml_gallocr_free(graph); + } + + return 0; +} diff --git a/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected b/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected new file mode 100644 index 0000000..dc3f1aa --- /dev/null +++ b/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected @@ -0,0 +1,2 @@ +| test.c:20:7:20:11 | test.c:20:7:20:11 | The variable `graph` is deallocated on line 16 and subsequently used on line 20 | +| test.c:21:21:21:25 | test.c:21:21:21:25 | The variable `graph` is deallocated on line 16 and subsequently used on line 21 | diff --git a/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.qlref b/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.qlref new file mode 100644 index 0000000..2569367 --- /dev/null +++ b/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.qlref @@ -0,0 +1 @@ +ml/LocalUseAfterFree.ql \ No newline at end of file diff --git a/cpp/test/query-tests/ml/LocalUseAfterFree/test.c b/cpp/test/query-tests/ml/LocalUseAfterFree/test.c new file mode 100644 index 0000000..207d60f --- /dev/null +++ b/cpp/test/query-tests/ml/LocalUseAfterFree/test.c @@ -0,0 +1,63 @@ +#include "../../../include/ggml/ggml-alloc.h" + +int condition(int flag) { + return (flag == 1); +} + +void use(ggml_gallocr_t graph) { + // Operations on graph. +} + +int bad(int flag) { + ggml_gallocr_t graph = ggml_gallocr_new(0); + + if (condition(flag)) { + // `graph` may be freed here. + ggml_gallocr_free(graph); + } + + // Potential use-after-free here. + use(graph); + ggml_gallocr_free(graph); + return 0; +} + +ggml_gallocr_t good() { + ggml_gallocr_t graph = ggml_gallocr_new(0); + return graph; +} + +int alsoGood(int flag) { + ggml_gallocr_t graph0 = ggml_gallocr_new(0); + ggml_gallocr_t graph1 = ggml_gallocr_new(0); + + if (condition(flag)) { + // `graph0` may be freed here + ggml_gallocr_free(graph0); + // but is immediately re-assigned here. + graph0 = graph1; + } + + // `graph0` is always allocated here. + use(graph0); + + ggml_gallocr_free(graph0); + ggml_gallocr_free(graph1); + + return 0; +} + +int main(int argc, char** argv) { + int flag = 0; + + ggml_gallocr_t graph = good(); + bad(flag); + + if (condition(flag)) { + ggml_gallocr_free(graph); + } else { + ggml_gallocr_free(graph); + } + + return alsoGood(flag); +} diff --git a/cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.expected b/cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.expected new file mode 100644 index 0000000..6629047 --- /dev/null +++ b/cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.expected @@ -0,0 +1 @@ +| test.c:9:3:9:18 | test.c:9:3:9:18 | The return value of `ggml_gallocr_new` is discarded here | diff --git a/cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.qlref b/cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.qlref new file mode 100644 index 0000000..f489e1a --- /dev/null +++ b/cpp/test/query-tests/ml/ReturnValueNotUsed/ReturnValueNotUsed.qlref @@ -0,0 +1 @@ +ml/ReturnValueNotUsed.ql \ No newline at end of file diff --git a/cpp/test/query-tests/ml/ReturnValueNotUsed/test.c b/cpp/test/query-tests/ml/ReturnValueNotUsed/test.c new file mode 100644 index 0000000..7c45ee4 --- /dev/null +++ b/cpp/test/query-tests/ml/ReturnValueNotUsed/test.c @@ -0,0 +1,27 @@ +#include "../../../include/ggml/ggml-alloc.h" + +void use(ggml_gallocr_t graph) { + // Operations on graph. + ggml_gallocr_free(graph); +} + +int bad() { + ggml_gallocr_new(0); + return 0; +} + +void good() { + ggml_gallocr_t graph = ggml_gallocr_new(0); + ggml_gallocr_free(graph); +} + +int alsoGood() { + use(ggml_gallocr_new(0)); + return 0; +} + +int main(int argc, char** argv) { + bad(); + good(); + return alsoGood(); +} From ae3f1bf4b598fb6b306c950afebe5de5b61d20ab Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 15:55:03 +0200 Subject: [PATCH 03/19] Optimized `LocalMemoryLeak` query --- .../trailofbits/ml/common/CustomAllocator.qll | 228 ++++++++++-------- cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll | 4 +- cpp/src/ml/LocalMemoryLeak.ql | 12 +- .../library-tests/ml/CustomAllocator/test.c | 1 - .../LocalMemoryLeak/LocalMemoryLeak.expected | 3 +- .../query-tests/ml/LocalMemoryLeak/test.c | 27 +++ 6 files changed, 170 insertions(+), 105 deletions(-) diff --git a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll b/cpp/lib/trailofbits/ml/common/CustomAllocator.qll index 28dbdbe..08c39c4 100644 --- a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll +++ b/cpp/lib/trailofbits/ml/common/CustomAllocator.qll @@ -1,13 +1,16 @@ import cpp import ReturnValue +import trailofbits.ml.libraries + +private import semmle.code.cpp.controlflow.Nullness private import semmle.code.cpp.dataflow.new.DataFlow private import semmle.code.cpp.controlflow.StackVariableReachability /** * A custom `alloc` function which returns a pointer to the allocated memory. */ -abstract class Alloc extends MustCheck {} +abstract class Alloc extends MustUse {} /** * A custom `free` which takes a pointer to the allocated memory as its only @@ -15,6 +18,24 @@ abstract class Alloc extends MustCheck {} */ abstract class Free extends Function {} +/** + * A call to `free` for some custom allocator. + */ +class AllocCall extends FunctionCall { + AllocCall() { + this.getTarget() instanceof Alloc + } +} + +/** + * A call to `free` for some custom allocator. + */ +class FreeCall extends FunctionCall { + FreeCall() { + this.getTarget() instanceof Free + } +} + /** * A custom allocator is a pair of functions `(alloc, free)`. We assume that * `alloc` returns a pointer to the allocated memory, and that `free` takes @@ -22,102 +43,119 @@ abstract class Free extends Function {} */ abstract class CustomAllocator extends string { - bindingset[this] - CustomAllocator() { any() } - - /** - * Is true if `f` is an `alloc` function for the custom allocator. (There - * may be more than one function that serves as an `alloc` function for the - * allocator.) - * - * If the `alloc` function takes the allocated pointer as an argument, override - * `isAllocatedBy` directly instead. - */ - abstract predicate isAlloc(Function f); - - /** - * Is true if `f` is a `free` function for the custom allocator. (There - * may be more than one function that serves as a `free` function for the - * allocator.) - * - * If the `free` function takes more than one argument, override `isFreedBy` - * directly instead. - */ - abstract predicate isFree(Function f); - - /** - * Returns a call to an `alloc` function. - */ - FunctionCall getAnAllocCall() { - this.isAlloc(result.getTarget()) - } - - /** - * Returns a call to a `free` function. - */ - FunctionCall getAFreeCall() { - this.isFree(result.getTarget()) - } - - /** - * True if `var` is allocated by the `alloc` call. - */ - predicate isAllocatedBy(FunctionCall alloc, Variable var) { - alloc = this.getAnAllocCall() and alloc = var.getAnAssignedValue() - } - - /** - * True if `var` is freed by the `free` call. - */ - predicate isFreedBy(FunctionCall free, Variable var) { - free = this.getAFreeCall() and free.getAnArgument() = var.getAnAccess() - } + bindingset[this] + CustomAllocator() { any() } + + /** + * Is true if `f` is an `alloc` function for the custom allocator. (There + * may be more than one function that serves as an `alloc` function for the + * allocator.) + * + * If the `alloc` function takes the allocated pointer as an argument, override + * `isAllocatedBy` directly instead. + */ + abstract predicate isAlloc(Alloc f); + + /** + * Is true if `f` is a `free` function for the custom allocator. (There + * may be more than one function that serves as a `free` function for the + * allocator.) + * + * If the `free` function takes more than one argument, override `isFreedBy` + * directly instead. + */ + abstract predicate isFree(Free f); + + /** + * Returns a call to an `alloc` function. + */ + AllocCall getAnAllocCall() { + this.isAlloc(result.getTarget()) + } + + /** + * Returns a call to a `free` function. + */ + FreeCall getAFreeCall() { + this.isFree(result.getTarget()) + } + + /** + * True if `var` is allocated by the `alloc` call. + */ + predicate isAllocatedBy(AllocCall alloc, Variable var) { + alloc = this.getAnAllocCall() and alloc = var.getAnAssignedValue() + } + + /** + * True if `var` is freed by the `free` call. + */ + predicate isFreedBy(FreeCall free, Variable var) { + free = this.getAFreeCall() and free.getArgument(0) = var.getAnAccess() + } } class LocalMemoryLeak extends StackVariableReachabilityWithReassignment { - CustomAllocator alloc; - - LocalMemoryLeak() { - this = "LocalMemoryLeak" - } - - override predicate isSourceActual(ControlFlowNode node, StackVariable var) { - alloc.isAllocatedBy(node, var) - } - - override predicate isBarrier(ControlFlowNode node, StackVariable var) { - alloc.isFreedBy(node, var) - } - - override predicate isSinkActual(ControlFlowNode node, StackVariable var) { - // A sink is a return statement not returning the allocated variable. - node instanceof ReturnStmt and not node.(ReturnStmt).getExpr() = var.getAnAccess() - } + CustomAllocator alloc; + + LocalMemoryLeak() { + this = "LocalMemoryLeak" } - - class LocalUseAfterFree extends StackVariableReachabilityWithReassignment { - CustomAllocator alloc; - - LocalUseAfterFree() { - this = "LocalUseAfterFree" - } - - override predicate isSourceActual(ControlFlowNode node, StackVariable var) { - alloc.isFreedBy(node, var) - } - - override predicate isSinkActual(ControlFlowNode node, StackVariable var) { - // A sink is an access which is not a reassignment. - node = var.getAnAccess() and not this.isAnAssignment(node, var) - } - - override predicate isBarrier(ControlFlowNode node, StackVariable var) { - // Stop tracking the variable if it is reassigned. - this.isAnAssignment(node, var) - } + + override predicate isSourceActual(ControlFlowNode node, StackVariable var) { + alloc.isAllocatedBy(node, var) + } + + override predicate isBarrier(ControlFlowNode node, StackVariable var) { + // A barrier is a call to `free`. + alloc.isFreedBy(node, var) + } + + override predicate isSinkActual(ControlFlowNode node, StackVariable var) { + // A sink is either the last statement in the parent scope of the allocated + // variable, or a return statement in the parent scope which does not return + // the allocated variable. + ( + // `node` represents a return statement in the parent scope. + node.(ReturnStmt).getEnclosingElement*() = var.getParentScope() or + // `node` represents the last statement in the parent scope. + node = var.getParentScope().(BlockStmt).getLastStmtIn() + ) and + // `node` does not represent a return statement returning the allocated value. + not node.(ReturnStmt).getExpr() = var.getAnAccess() and + // `node` does not represent a call to `free`, freeing the allocated value. + not isBarrier(node.(Stmt).getAChild*(), var) and + // `node` is not guarded by a condition ensuring that the variable is `NULL`. + not checkedNull(var, node) + } +} + +class LocalUseAfterFree extends StackVariableReachabilityWithReassignment { + CustomAllocator alloc; - // Returns true if the `node` is the lvalue of an assignment to `var`. - predicate isAnAssignment(ControlFlowNode node, StackVariable var) { - node = var.getAnAssignment().getLValue() - } - } \ No newline at end of file + LocalUseAfterFree() { + this = "LocalUseAfterFree" + } + + override predicate isSourceActual(ControlFlowNode node, StackVariable var) { + alloc.isFreedBy(node, var) + } + + override predicate isSinkActual(ControlFlowNode node, StackVariable var) { + // A sink is an access which is not a reassignment. + node = var.getAnAccess() and + not isAnAssignment(node, var) + } + + override predicate isBarrier(ControlFlowNode node, StackVariable var) { + // Stop tracking the variable if it is reassigned. + this.isAnAssignment(node, var) + } + + /** + * Returns true if the `node` is the lvalue of an assignment to `var`. + */ + predicate isAnAssignment(ControlFlowNode node, StackVariable var) { + node = var.getAnAssignedValue() + } +} diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll index 078633a..a28f4b2 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll @@ -58,11 +58,11 @@ class GGML_gallocr_get_buffer_size extends MustUse { class GraphAllocator extends CustomAllocator { GraphAllocator() { this = "GraphAllocator" } - override predicate isAlloc(Function f) { + override predicate isAlloc(Alloc f) { (f instanceof GGML_gallocr_new) or (f instanceof GGML_gallocr_new_n) } - override predicate isFree(Function f) { + override predicate isFree(Free f) { f instanceof GGML_gallocr_free } } \ No newline at end of file diff --git a/cpp/src/ml/LocalMemoryLeak.ql b/cpp/src/ml/LocalMemoryLeak.ql index 4a95dd8..d3b1e95 100644 --- a/cpp/src/ml/LocalMemoryLeak.ql +++ b/cpp/src/ml/LocalMemoryLeak.ql @@ -1,6 +1,6 @@ /** * @name Memory leak related to custom allocator - * @id tob/cpp/local-memory-leak + * @id tob/cpp/memory-leak * @description Finds memory leaks related to GGML custom allocators * @kind problem * @tags correctness ml @@ -18,16 +18,16 @@ string toLine(ControlFlowNode node) { result = node.getLocation().getStartLine() string toMessage(ControlFlowNode source, ControlFlowNode sink, StackVariable var) { result = "The variable `" + var + "` is allocated on line " + - toLine(source) + " and leaks on line " + toLine(sink) + toLine(source) + " and may leak on line " + toLine(sink) } from LocalMemoryLeak leak, - ControlFlowNode source, - ControlFlowNode sink, - StackVariable var -where + AllocCall source, + Stmt sink, + SemanticStackVariable var +where leak.reaches(source, var, sink) select source.getLocation(), toMessage(source, sink, var) \ No newline at end of file diff --git a/cpp/test/library-tests/ml/CustomAllocator/test.c b/cpp/test/library-tests/ml/CustomAllocator/test.c index 0ff12e1..52f3ee5 100644 --- a/cpp/test/library-tests/ml/CustomAllocator/test.c +++ b/cpp/test/library-tests/ml/CustomAllocator/test.c @@ -17,7 +17,6 @@ int bad(int flag) { return 0; } - ggml_gallocr_t good() { ggml_gallocr_t graph = ggml_gallocr_new(0); return graph; diff --git a/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected b/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected index 0452183..fe6c416 100644 --- a/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected +++ b/cpp/test/query-tests/ml/LocalMemoryLeak/LocalMemoryLeak.expected @@ -1 +1,2 @@ -| test.c:8:26:8:41 | test.c:8:26:8:41 | The variable `graph` is allocated on line 8 and leaks on line 12 | +| test.c:8:26:8:41 | test.c:8:26:8:41 | The variable `graph` is allocated on line 8 and may leak on line 12 | +| test.c:25:28:25:43 | test.c:25:28:25:43 | The variable `graph` is allocated on line 25 and may leak on line 28 | diff --git a/cpp/test/query-tests/ml/LocalMemoryLeak/test.c b/cpp/test/query-tests/ml/LocalMemoryLeak/test.c index 0ff12e1..f0f8d44 100644 --- a/cpp/test/query-tests/ml/LocalMemoryLeak/test.c +++ b/cpp/test/query-tests/ml/LocalMemoryLeak/test.c @@ -17,17 +17,43 @@ int bad(int flag) { return 0; } +void use(ggml_gallocr_t graph) { } + +void alsoBad() { + unsigned int order = 0; + for (int i = 0; i < 8; ++i) { + ggml_gallocr_t graph = ggml_gallocr_new(0); + use(graph); + // `graph` leaks here in each iteration. + order++; + } +} ggml_gallocr_t good() { ggml_gallocr_t graph = ggml_gallocr_new(0); return graph; } +int alsoGood() { + ggml_gallocr_t graph = ggml_gallocr_new(0); + if (!graph) { + // `graph is `NULL` and does not leak here. + return -1; + } + use(graph); + + ggml_gallocr_free(graph); + return 0; +} + int main(int argc, char** argv) { int flag = 0; ggml_gallocr_t graph = good(); + alsoGood(); + bad(flag); + alsoBad(); if (condition(flag)) { ggml_gallocr_free(graph); @@ -35,5 +61,6 @@ int main(int argc, char** argv) { ggml_gallocr_free(graph); } + return 0; } From 02a1e3a492369ff8ea3ec2c49f16a70e420716b1 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 15:56:00 +0200 Subject: [PATCH 04/19] Small optimization of `LocalUseAfterFree` query --- cpp/src/ml/LocalUseAfterFree.ql | 6 +++--- .../ml/LocalUseAfterFree/LocalUseAfterFree.expected | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/src/ml/LocalUseAfterFree.ql b/cpp/src/ml/LocalUseAfterFree.ql index 423d83c..a184007 100644 --- a/cpp/src/ml/LocalUseAfterFree.ql +++ b/cpp/src/ml/LocalUseAfterFree.ql @@ -24,9 +24,9 @@ string toMessage(ControlFlowNode source, ControlFlowNode sink, StackVariable var from LocalUseAfterFree uaf, - ControlFlowNode source, - ControlFlowNode sink, - StackVariable var + FreeCall source, + VariableAccess sink, + SemanticStackVariable var where uaf.reaches(source, var, sink) select diff --git a/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected b/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected index dc3f1aa..ce71afe 100644 --- a/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected +++ b/cpp/test/query-tests/ml/LocalUseAfterFree/LocalUseAfterFree.expected @@ -1,2 +1,4 @@ | test.c:20:7:20:11 | test.c:20:7:20:11 | The variable `graph` is deallocated on line 16 and subsequently used on line 20 | | test.c:21:21:21:25 | test.c:21:21:21:25 | The variable `graph` is deallocated on line 16 and subsequently used on line 21 | +| test.c:31:9:31:13 | test.c:31:9:31:13 | The variable `graph` is deallocated on line 32 and subsequently used on line 31 | +| test.c:32:23:32:27 | test.c:32:23:32:27 | The variable `graph` is deallocated on line 32 and subsequently used on line 32 | From 19acb21bb6469b0abd00c8713e57ab56423f22ff Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 15:56:35 +0200 Subject: [PATCH 05/19] Fixed formatting of `ReturnValue.qll` --- cpp/lib/trailofbits/ml/common/ReturnValue.qll | 132 +++++++++--------- .../query-tests/ml/LocalUseAfterFree/test.c | 17 +++ 2 files changed, 83 insertions(+), 66 deletions(-) diff --git a/cpp/lib/trailofbits/ml/common/ReturnValue.qll b/cpp/lib/trailofbits/ml/common/ReturnValue.qll index cef6719..9eb3673 100644 --- a/cpp/lib/trailofbits/ml/common/ReturnValue.qll +++ b/cpp/lib/trailofbits/ml/common/ReturnValue.qll @@ -16,73 +16,73 @@ abstract class MustCheck extends Function { } * The return value of a function. */ class ReturnValue extends FunctionCall { - /** - * Returns the function that the return value corresponds to. - */ - Function getFunction() { - result = this.getTarget() - } - /** - * True if the return value must be used. - */ - predicate mustUse() { - this.getTarget() instanceof MustUse - } + /** + * Returns the function that the return value corresponds to. + */ + Function getFunction() { + result = this.getTarget() + } + /** + * True if the return value must be used. + */ + predicate mustUse() { + this.getTarget() instanceof MustUse + } - /** - * True if the return value must be used. - */ - predicate mustCheck() { - this.getTarget() instanceof MustCheck - } + /** + * True if the return value must be used. + */ + predicate mustCheck() { + this.getTarget() instanceof MustCheck + } - /** - * Returns true if the corresponding function call is not an expression - * statement. - */ - predicate isUsed() { - not exists(ExprStmt stmt | this = stmt.getExpr()) - } + /** + * Returns true if the corresponding function call is not an expression + * statement. + */ + predicate isUsed() { + not exists(ExprStmt stmt | this = stmt.getExpr()) + } - /** - * Returns true if the return value flows into a conditional statement or - * expression, or a return statement. - */ - predicate isChecked() { - // The return value flows into the condition of an if-statement. - exists (IfStmt is | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(is.getCondition().getAChild*()) - ) - ) or - // The return value flows into the condition of a while-statement. - exists (WhileStmt ws | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(ws.getCondition().getAChild*()) - ) - ) or - // The return value flows into the condition of a switch-statement. - exists (SwitchStmt ss | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(ss.getExpr().getAChild*()) - ) - ) or - // The return value flows into a conditional expression. - exists (ConditionalExpr ce | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(ce.getCondition().getAChild*()) - ) - ) or - // The return value is returned by the function. - exists (ReturnStmt rs | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(rs.getExpr().getAChild*()) - ) - ) - } + /** + * Returns true if the return value flows into a conditional statement or + * expression, or a return statement. + */ + predicate isChecked() { + // The return value flows into the condition of an if-statement. + exists (IfStmt is | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(is.getCondition().getAChild*()) + ) + ) or + // The return value flows into the condition of a while-statement. + exists (WhileStmt ws | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(ws.getCondition().getAChild*()) + ) + ) or + // The return value flows into the condition of a switch-statement. + exists (SwitchStmt ss | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(ss.getExpr().getAChild*()) + ) + ) or + // The return value flows into a conditional expression. + exists (ConditionalExpr ce | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(ce.getCondition().getAChild*()) + ) + ) or + // The return value is returned by the function. + exists (ReturnStmt rs | + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(rs.getExpr().getAChild*()) + ) + ) + } } diff --git a/cpp/test/query-tests/ml/LocalUseAfterFree/test.c b/cpp/test/query-tests/ml/LocalUseAfterFree/test.c index 207d60f..01ab198 100644 --- a/cpp/test/query-tests/ml/LocalUseAfterFree/test.c +++ b/cpp/test/query-tests/ml/LocalUseAfterFree/test.c @@ -22,7 +22,24 @@ int bad(int flag) { return 0; } +void alsoBad(int count) { + ggml_gallocr_t graph = ggml_gallocr_new(0); + + for (int i = 0; i < count; i++) { + // Potential use-after-free here when `graph` is + // freed in the previous iteration of the loop. + use(graph); + ggml_gallocr_free(graph); + } +} + ggml_gallocr_t good() { + for (int i = 0; i < 8; i++) { + ggml_gallocr_t graph = ggml_gallocr_new(0); + use(graph); + ggml_gallocr_free(graph); + } + ggml_gallocr_t graph = ggml_gallocr_new(0); return graph; } From 1879badcab9a2bf86e9b648dc060b182440bd6b5 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 15:57:44 +0200 Subject: [PATCH 06/19] Updated `ContextAllocator` with new `CustomAllocator` API --- cpp/lib/trailofbits/ml/ggml.qll | 1 + cpp/lib/trailofbits/ml/ggml/ggml.qll | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/lib/trailofbits/ml/ggml.qll b/cpp/lib/trailofbits/ml/ggml.qll index 48b0f2a..6897ee4 100644 --- a/cpp/lib/trailofbits/ml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml.qll @@ -1 +1,2 @@ import ggml.ggml_alloc +import ggml.ggml \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/ggml/ggml.qll b/cpp/lib/trailofbits/ml/ggml/ggml.qll index 339ec1b..bfbbd63 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml.qll @@ -22,11 +22,11 @@ class ContextAllocator extends CustomAllocator { ContextAllocator() { this = "ContextAllocator" } - override predicate isAlloc(Function f) { + override predicate isAlloc(Alloc f) { f instanceof GGML_init } - override predicate isFree(Function f) { + override predicate isFree(Free f) { f instanceof GGML_free } } \ No newline at end of file From ac31b8a44c8356e7ed46384394cda26c456fb6d4 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 13 May 2024 15:59:57 +0200 Subject: [PATCH 07/19] Fixed test case --- .../ml/CustomAllocator/CustomAllocator.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected b/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected index b547a08..0af4963 100644 --- a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected +++ b/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected @@ -1,5 +1,5 @@ | 8 | `graph` is allocated here | | 16 | `graph` is freed here | -| 22 | `graph` is allocated here | -| 33 | `graph` is freed here | -| 35 | `graph` is freed here | +| 21 | `graph` is allocated here | +| 32 | `graph` is freed here | +| 34 | `graph` is freed here | From 4e3da35487cd88007b0db478cccdec06319ca442 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Fri, 17 May 2024 14:00:37 +0200 Subject: [PATCH 08/19] Updated query metadata --- cpp/src/ml/LocalMemoryLeak.ql | 6 +++--- cpp/src/ml/LocalUseAfterFree.ql | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/src/ml/LocalMemoryLeak.ql b/cpp/src/ml/LocalMemoryLeak.ql index d3b1e95..9309a97 100644 --- a/cpp/src/ml/LocalMemoryLeak.ql +++ b/cpp/src/ml/LocalMemoryLeak.ql @@ -1,7 +1,7 @@ /** - * @name Memory leak related to custom allocator - * @id tob/cpp/memory-leak - * @description Finds memory leaks related to GGML custom allocators + * @name Memory leak from a GGML custom allocator + * @id tob/cpp/ggml-memory-leak + * @description A value allocated using a GGML custom allocator is never freed, leaking the corresponding memory * @kind problem * @tags correctness ml * @problem.severity warning diff --git a/cpp/src/ml/LocalUseAfterFree.ql b/cpp/src/ml/LocalUseAfterFree.ql index a184007..ddebb03 100644 --- a/cpp/src/ml/LocalUseAfterFree.ql +++ b/cpp/src/ml/LocalUseAfterFree.ql @@ -1,7 +1,7 @@ /** - * @name Use after free related to custom allocator - * @id tob/cpp/local-use-after-free - * @description Finds use-after-frees related to GGML custom allocators + * @name Use after free using a GGML custom allocator + * @id tob/cpp/ggml-use-after-free + * @description A value allocated using a GGML custom allocator is freed, and then reused without being reallocated. * @kind problem * @tags correctness ml * @problem.severity warning From 22cd4a57102d538b0c8f04850f40797eaef964d6 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Fri, 17 May 2024 14:01:52 +0200 Subject: [PATCH 09/19] Added a number of new custom allocators --- cpp/lib/trailofbits/ml/ggml.qll | 3 +- cpp/lib/trailofbits/ml/ggml/ggml.qll | 51 +++++- cpp/lib/trailofbits/ml/ggml/ggml_backend.qll | 170 +++++++++++++++++++ 3 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 cpp/lib/trailofbits/ml/ggml/ggml_backend.qll diff --git a/cpp/lib/trailofbits/ml/ggml.qll b/cpp/lib/trailofbits/ml/ggml.qll index 6897ee4..6cd916c 100644 --- a/cpp/lib/trailofbits/ml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml.qll @@ -1,2 +1,3 @@ +import ggml.ggml import ggml.ggml_alloc -import ggml.ggml \ No newline at end of file +import ggml.ggml_backend \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/ggml/ggml.qll b/cpp/lib/trailofbits/ml/ggml/ggml.qll index bfbbd63..d9fd283 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml.qll @@ -18,15 +18,60 @@ class GGML_free extends Free { } } -class ContextAllocator extends CustomAllocator { - ContextAllocator() { - this = "ContextAllocator" +/** + * GGML_API struct gguf_context * gguf_init_empty(void); + */ +class GGUF_init_empty extends Alloc { + GGUF_init_empty() { + this.getName() = "gguf_init_empty" + } +} + +/** + * GGML_API struct gguf_context * gguf_init_from_file( + * const char * fname, + * struct gguf_init_params params + * ); + */ +class GGUF_init_from_file extends Alloc { + GGUF_init_from_file() { + this.getName() = "gguf_init_from_file" + } +} + +/** + * GGML_API void gguf_free(struct gguf_context * ctx); + */ +class GGUF_free extends Free { + GGUF_free() { + this.getName() = "gguf_free" + } +} + +class GGMLContextAllocator extends CustomAllocator { + GGMLContextAllocator() { + this = "GGMLContextAllocator" } override predicate isAlloc(Alloc f) { + // TODO: Overload `isAllocatedBy` to check if the `mem_buffer` field is + // not `NULL`. f instanceof GGML_init } override predicate isFree(Free f) { f instanceof GGML_free } +} + +class GGUFContextAllocator extends CustomAllocator { + GGUFContextAllocator() { + this = "GGUFContextAllocator" + } + override predicate isAlloc(Alloc f) { + (f instanceof GGUF_init_empty) or (f instanceof GGUF_init_from_file) + } + + override predicate isFree(Free f) { + f instanceof GGUF_free + } } \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll new file mode 100644 index 0000000..1b9f7a8 --- /dev/null +++ b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll @@ -0,0 +1,170 @@ +import cpp +import trailofbits.ml.common + +/** + * GGML_API ggml_backend_buffer_t ggml_backend_buft_alloc_buffer( + * ggml_backend_buffer_type_t buft, + * size_t size + * ); + */ +class GGML_backend_buft_alloc_buffer extends Alloc { + GGML_backend_buft_alloc_buffer() { + this.getName() = "ggml_backend_buft_alloc_buffer" + } +} + +/** + * GGML_API void ggml_backend_buffer_free(ggml_backend_buffer_t buffer); + */ +class GGML_backend_buffer_free extends Free { + GGML_backend_buffer_free() { + this.getName() = "ggml_backend_buffer_free" + } +} + +/** + * GGML_API ggml_backend_sched_t ggml_backend_sched_new( + * ggml_backend_t * backends, + * ggml_backend_buffer_type_t * bufts, + * int n_backends, + * size_t graph_size, + * bool parallel + * ); + */ +class GGML_backend_sched_new extends Alloc { + GGML_backend_sched_new() { + this.getName() = "ggml_backend_sched_new" + } +} + +/** + * GGML_API void ggml_backend_sched_free(ggml_backend_sched_t sched); + */ +class GGML_backend_sched_free extends Free { + GGML_backend_sched_free() { + this.getName() = "ggml_backend_sched_free" + } +} + +/** + * GGML_API struct ggml_backend_graph_copy ggml_backend_graph_copy( + * ggml_backend_t backend, + * struct ggml_cgraph * graph + * ); + */ +class GGML_backend_graph_copy extends Alloc { + GGML_backend_graph_copy() { + this.getName() = "ggml_backend_graph_copy" + } +} + +/** + * GGML_API void ggml_backend_graph_copy_free(struct ggml_backend_graph_copy copy); + */ +class GGML_backend_graph_copy_free extends Free { + GGML_backend_graph_copy_free() { + this.getName() = "ggml_backend_graph_copy_free" + } +} + +/** + * GGML_API ggml_backend_graph_plan_t ggml_backend_graph_plan_create( + * ggml_backend_t backend, + * struct ggml_cgraph *cgraph + * ); + */ +class GGML_backend_graph_plan_create extends Alloc { + GGML_backend_graph_plan_create() { + this.getName() = "ggml_backend_graph_plan_create" + } +} + +/** + * GGML_API void ggml_backend_graph_plan_free( + * ggml_backend_t backend, + * ggml_backend_graph_plan_t plan + * ); + */ +class GGML_backend_graph_plan_free extends Free { + GGML_backend_graph_plan_free() { + this.getName() = "ggml_backend_graph_plan_free" + } +} + +/** + * GGML_API ggml_backend_event_t ggml_backend_event_new(ggml_backend_t backend); + */ +class GGML_backend_event_new extends Alloc { + GGML_backend_event_new() { + this.getName() = "ggml_backend_event_new" + } +} + +/** + * GGML_API void ggml_backend_event_free(ggml_backend_event_t event); + */ +class GGML_backend_event_free extends Free { + GGML_backend_event_free() { + this.getName() = "ggml_backend_event_free" + } +} + +class BackendBufferAllocator extends CustomAllocator { + BackendBufferAllocator() { this = "BackendBufferAllocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_buft_alloc_buffer + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_buffer_free + } +} + +class BackendSchedulerAllocator extends CustomAllocator { + BackendSchedulerAllocator() { this = "BackendSchedulerAllocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_sched_new + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_sched_free + } +} + +class BackendGraphCopyAllocator extends CustomAllocator { + BackendGraphCopyAllocator() { this = "BackendGraphCopyAllocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_graph_copy + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_graph_copy_free + } +} + +class BackendGraphPlanAllocator extends CustomAllocator { + BackendGraphPlanAllocator() { this = "BackendGraphPlanAllocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_graph_plan_create + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_graph_plan_free + } +} + +class BackendEventAllocator extends CustomAllocator { + BackendEventAllocator() { this = "BackendEventAllocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_event_new + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_event_free + } +} \ No newline at end of file From 6227e15acfd050b2666340f5aaf24cc62f9c09f2 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Fri, 17 May 2024 14:10:26 +0200 Subject: [PATCH 10/19] Added escape analysis This analysis is used to detect false positives in the `LocalMemoryLeak.ql` query. --- cpp/lib/trailofbits/ml/common.qll | 2 + .../trailofbits/ml/common/EscapeAnalysis.qll | 154 ++++++++++++++++++ cpp/lib/trailofbits/ml/common/MethodCall.qll | 29 ++++ cpp/test/include/std/vector.hpp | 9 + .../ml/EscapeAnalysis/EscapeAnalysis.expected | 10 ++ .../ml/EscapeAnalysis/EscapeAnalysis.ql | 10 ++ .../library-tests/ml/EscapeAnalysis/test.cpp | 79 +++++++++ 7 files changed, 293 insertions(+) create mode 100644 cpp/lib/trailofbits/ml/common/EscapeAnalysis.qll create mode 100644 cpp/lib/trailofbits/ml/common/MethodCall.qll create mode 100644 cpp/test/include/std/vector.hpp create mode 100644 cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.expected create mode 100644 cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql create mode 100644 cpp/test/library-tests/ml/EscapeAnalysis/test.cpp diff --git a/cpp/lib/trailofbits/ml/common.qll b/cpp/lib/trailofbits/ml/common.qll index 0b145ed..e96f621 100644 --- a/cpp/lib/trailofbits/ml/common.qll +++ b/cpp/lib/trailofbits/ml/common.qll @@ -1,2 +1,4 @@ import common.CustomAllocator +import common.EscapeAnalysis +import common.MethodCall import common.ReturnValue \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/common/EscapeAnalysis.qll b/cpp/lib/trailofbits/ml/common/EscapeAnalysis.qll new file mode 100644 index 0000000..1ca70d4 --- /dev/null +++ b/cpp/lib/trailofbits/ml/common/EscapeAnalysis.qll @@ -0,0 +1,154 @@ +/** + * This library contains a best-effort escape analysis which is used to + * determine if an allocated value may escape the current function. To avoid + * performance issues we try to determine if the value escapes based on the + * given control flow node alone. + * + * To avoid false positives in the memory leak query (`LocalMemoryLeak.ql`), we + * over-estimate the number of values that escape the function. + */ +import cpp +import MethodCall + +/** + * True if the operation at `node` may cause the value of `var` to escape the + * enclosing function. + */ +predicate mayEscapeFunctionAt(ControlFlowNode node, SemanticStackVariable var) { + exists (EscapeAnalysis ea | ea.mayEscapeAt(node, var)) +} + +abstract class EscapeAnalysis extends string { + bindingset[this] + EscapeAnalysis() { any() } + + /** + * True if the operation at `node` may cause the value of `var` to escape the + * function. + */ + abstract predicate mayEscapeAt(ControlFlowNode node, SemanticStackVariable var); +} + +/** + * Captures values that are returned by the current function. + */ +class ReturnValueAnalysis extends EscapeAnalysis { + ReturnValueAnalysis() { + this = "ReturnValueAnalysis" + } + + override predicate mayEscapeAt(ControlFlowNode node, SemanticStackVariable var) { + // `node` is a return statement returning the variable `var`, or + // an expression containing the variable `var`. (This may lead to) + // false positives, but is intended to catch instances where `var` + // is returned through a struct, or through a function call. + node.(ReturnStmt).getExpr().getAChild*() = var.getAnAccess() + } +} + +/** + * Captures values that escape through an assignment to a pointer parameter. + * (We do not currently handle reassignments.) + */ +class PointerParameterAnalysis extends EscapeAnalysis { + PointerParameterAnalysis() { + this = "PointerParameterAnalysis" + } + + /** + * Returns a pointer parameter of the given function. + */ + private Parameter getAPointerParameter(Function f) { + result = f.getAParameter() and result.getType() instanceof PointerType + } + + /** + * Returns an access to a pointer parameter in the given function. + */ + private VariableAccess getAPointerParameterAccess(Function f) { + result = getAPointerParameter(f).getAnAccess() + } + + override predicate mayEscapeAt(ControlFlowNode node, SemanticStackVariable var) { + // `node` is an assignment of `var` to an lvalue containing a pointer + // parameter as a sub-expression. This is meant to cover the case when + // `var` is assigned to either + // + // 1. The (dereferenced) parameter directly + // 2. A parameter field access (in the case of a struct or class parameter) + // 3. An indexing operation on the parameter (in the case of an array or vector) + node.(AssignExpr).getRValue() = var.getAnAccess() and + // Using + rather than * here excludes the following case where the local + // variable `ptr` is simply reassigned. + // + // ```c + // void f(int *ptr) { + // int *x = malloc(sizeof(int)); + // ptr = x; + // } + // ``` + node.(AssignExpr).getLValue().getAChild+() = getAPointerParameterAccess(var.getFunction()) + } +} + +/** + * Captures values that escape through an assignment to a reference parameter. + * (We do not currently handle reassignments.) + */ +class ReferenceParameterAnalysis extends EscapeAnalysis { + ReferenceParameterAnalysis() { + this = "ReferenceParameterAnalysis" + } + + /** + * Returns a reference parameter of the given function. + */ + private Parameter getAReferenceParameter(Function f) { + result = f.getAParameter() and result.getType() instanceof ReferenceType + } + + /** + * Returns an access to a reference parameter in the given function. + */ + private VariableAccess getAReferenceParameterAccess(Function f) { + result = getAReferenceParameter(f).getAnAccess() + } + + override predicate mayEscapeAt(ControlFlowNode node, SemanticStackVariable var) { + // `node` is an assignment of `var` to an lvalue containing a reference + // parameter as a sub-expression. This is meant to cover the case when + // `var` is assigned to either + // + // 1. The parameter directly + // 2. A parameter field access (in the case of a struct or class parameter) + // 3. An indexing operation on the parameter (in the case of an array or vector) + node.(AssignExpr).getRValue() = var.getAnAccess() and + node.(AssignExpr).getLValue().getAChild*() = getAReferenceParameterAccess(var.getFunction()) + } +} + +class VectorParameterEscapeAnalysis extends EscapeAnalysis { + VectorParameterEscapeAnalysis() { + this = "VectorParameterEscapeAnalysis" + } + + /** + * True if the given call is a call to `vector::push_back` for some `T`. + */ + private predicate isVectorPushBack(MethodCall call, Expr vec, Expr elem) { + call.getClass().getName().matches("vector<%>") and + call.getTarget().getName() = "push_back" and + call.getThis() = vec and + call.getArgument(0) = elem + } + + override predicate mayEscapeAt(ControlFlowNode node, SemanticStackVariable var) { + exists (Expr expr, Parameter param | + // This is an imprecise way of catching both expressions like + // `v.push_back(x)` where `v` is a parameter, and expressions + // like `foo->v.push_back(x)` where `foo` is a parameter. + expr.getAChild*() = param.getAnAccess() and + isVectorPushBack(node, expr, var.getAnAccess()) + ) + } +} \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/common/MethodCall.qll b/cpp/lib/trailofbits/ml/common/MethodCall.qll new file mode 100644 index 0000000..50d8586 --- /dev/null +++ b/cpp/lib/trailofbits/ml/common/MethodCall.qll @@ -0,0 +1,29 @@ +import cpp + +class MethodCall extends FunctionCall { + MemberFunction method; + MethodCall() { + this = method.getACallToThisFunction() + } + + /** + * The called method. + */ + MemberFunction getMethod() { + result = method + } + + /** + * The instance of the class the method was called on. + */ + Expr getThis() { + result = this.getAChild() and result != this.getAnArgument() + } + + /** + * The class that this method is defined on. + */ + Type getClass() { + result = this.getThis().getType().stripType() + } +} diff --git a/cpp/test/include/std/vector.hpp b/cpp/test/include/std/vector.hpp new file mode 100644 index 0000000..3cbaaaf --- /dev/null +++ b/cpp/test/include/std/vector.hpp @@ -0,0 +1,9 @@ +namespace std { + template + class vector { + public: + vector() {} + + void push_back(const T& value) {} + }; +} \ No newline at end of file diff --git a/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.expected b/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.expected new file mode 100644 index 0000000..7fb04c4 --- /dev/null +++ b/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.expected @@ -0,0 +1,10 @@ +| test.cpp:18:3:18:10 | test.cpp:18:3:18:10 | x | +| test.cpp:24:3:24:13 | test.cpp:24:3:24:13 | x | +| test.cpp:30:3:30:9 | test.cpp:30:3:30:9 | x | +| test.cpp:36:3:36:11 | test.cpp:36:3:36:11 | x | +| test.cpp:42:5:42:13 | test.cpp:42:5:42:13 | x | +| test.cpp:48:6:48:14 | test.cpp:48:6:48:14 | x | +| test.cpp:54:9:54:17 | test.cpp:54:9:54:17 | x | +| test.cpp:60:10:60:18 | test.cpp:60:10:60:18 | x | +| test.cpp:66:5:66:13 | test.cpp:66:5:66:13 | x | +| test.cpp:72:5:72:31 | test.cpp:72:5:72:31 | x | diff --git a/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql b/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql new file mode 100644 index 0000000..893555b --- /dev/null +++ b/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql @@ -0,0 +1,10 @@ +import cpp +import trailofbits.ml.common + +from + ControlFlowNode node, + SemanticStackVariable var +where + mayEscapeFunctionAt(node, var) +select + node.getLocation(), var.getName() diff --git a/cpp/test/library-tests/ml/EscapeAnalysis/test.cpp b/cpp/test/library-tests/ml/EscapeAnalysis/test.cpp new file mode 100644 index 0000000..248c83b --- /dev/null +++ b/cpp/test/library-tests/ml/EscapeAnalysis/test.cpp @@ -0,0 +1,79 @@ +#include "../../../include/std/vector.hpp" + +typedef int* intptr_t; + +class Foo { +public: + int *x; + std::vector v; +}; + +struct bar_t { + int *x; +}; + +// `x` escapes through `var`. +void test_0(int **var) { + int *x = 0; + *var = x; +} + +// `x` escapes through `vars`. +void test_1(int **vars) { + int *x = 0; + vars[0] = x; +} + +// `x` escapes through `ptr`. +void test_2(intptr_t &ptr) { + int *x = 0; + ptr = x; +} + +// `x` escapes through `foo`. +void test_3(Foo &foo) { + int *x = 0; + foo.x = x; +} + +// `x` escapes through `v`. +void test_4(std::vector &v) { + int *x = 0; + v.push_back(x); +} + +// `x` escapes through `v`. +void test_5(std::vector *v) { + int *x = 0; + v->push_back(x); +} + +// `x` escapes through `foo`. +void test_6(Foo &foo) { + int *x = 0; + foo.v.push_back(x); +} + +// `x` escapes through `foo`. +void test_7(Foo *foo) { + int *x = 0; + foo->v.push_back(x); +} + +// `x` escapes through return value. +int *test_8() { + int *x = 0; + return x; +} + +// `x` escapes through return value. +struct bar_t test_9() { + int *x = 0; + return (struct bar_t){ x }; +} + +// `x` does not escape. +void test_10(int *p) { + int *x = 0; + p = x; +} From d9e4ee4171cf965b792d4da1e9edbe48e011e74d Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Fri, 17 May 2024 14:11:14 +0200 Subject: [PATCH 11/19] Added escape analysis to `LocalMemoryLeak` --- cpp/lib/trailofbits/ml/common/CustomAllocator.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll b/cpp/lib/trailofbits/ml/common/CustomAllocator.qll index 08c39c4..8d829db 100644 --- a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll +++ b/cpp/lib/trailofbits/ml/common/CustomAllocator.qll @@ -107,8 +107,9 @@ class LocalMemoryLeak extends StackVariableReachabilityWithReassignment { } override predicate isBarrier(ControlFlowNode node, StackVariable var) { - // A barrier is a call to `free`. - alloc.isFreedBy(node, var) + // A barrier is a call to `free` or an assignment to a variable which + // escapes the current function. + alloc.isFreedBy(node, var) or mayEscapeFunctionAt(node, var) } override predicate isSinkActual(ControlFlowNode node, StackVariable var) { From 493b1f2fd09460365b47f4dc58acda488712e418 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Fri, 17 May 2024 14:13:11 +0200 Subject: [PATCH 12/19] Updated query metadata --- cpp/src/ml/ReturnValueNotChecked.ql | 6 +++--- cpp/src/ml/ReturnValueNotUsed.ql | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/src/ml/ReturnValueNotChecked.ql b/cpp/src/ml/ReturnValueNotChecked.ql index e9a6a1c..6ee4eaf 100644 --- a/cpp/src/ml/ReturnValueNotChecked.ql +++ b/cpp/src/ml/ReturnValueNotChecked.ql @@ -1,7 +1,7 @@ /** - * @name Function return value is discarded - * @id tob/cpp/return-value-not-checked - * @description Finds function calls where the return value is expected to be used + * @name Function return value is not checked + * @id tob/cpp/ggml-return-value-not-checked + * @description The return value from this function is expected to be checked in some way, but it is not * @kind problem * @tags correctness ml * @problem.severity warning diff --git a/cpp/src/ml/ReturnValueNotUsed.ql b/cpp/src/ml/ReturnValueNotUsed.ql index 6f9f9fb..3bc1548 100644 --- a/cpp/src/ml/ReturnValueNotUsed.ql +++ b/cpp/src/ml/ReturnValueNotUsed.ql @@ -1,7 +1,7 @@ /** * @name Function return value is discarded - * @id tob/cpp/return-value-not-used - * @description Finds function calls where the return value is expected to be used + * @id tob/cpp/ggml-return-value-not-used + * @description The return value from this function is expected to be used, but it is immediately discarded * @kind problem * @tags correctness ml * @problem.severity warning From c60fae495f239349f619366ed43f14aa5b5f3ec3 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Fri, 17 May 2024 16:37:41 +0200 Subject: [PATCH 13/19] Added support for custom error messages for `MustUse` and `MustCheck` --- cpp/lib/trailofbits/ml/common/ReturnValue.qll | 20 +++++++++++++++++-- cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll | 12 +++++++++++ cpp/src/ml/ReturnValueNotChecked.ql | 2 +- cpp/src/ml/ReturnValueNotUsed.ql | 2 +- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/cpp/lib/trailofbits/ml/common/ReturnValue.qll b/cpp/lib/trailofbits/ml/common/ReturnValue.qll index 9eb3673..19a8143 100644 --- a/cpp/lib/trailofbits/ml/common/ReturnValue.qll +++ b/cpp/lib/trailofbits/ml/common/ReturnValue.qll @@ -5,12 +5,28 @@ import semmle.code.cpp.dataflow.new.DataFlow /** * Identifies functions where the return value must be used in some way. */ -abstract class MustUse extends Function { } +abstract class MustUse extends Function { + /** + * Override this for more detailed messages on why the return value is + * expected to be used. + */ + string getMessage() { + result = "The return value of `" + this.getName() + "` is discarded here" + } +} /** * Identifies functions where the return value must be checked. */ -abstract class MustCheck extends Function { } +abstract class MustCheck extends Function { + /** + * Override this method for more detailed messages on why and how the return + * value should be checked. + */ + string getMessage() { + result = "The return value of `" + this.getName() + "` is not checked" + } +} /** * The return value of a function. diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll index a28f4b2..f599626 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll @@ -28,6 +28,10 @@ class GGML_gallocr_free extends Free { */ class GGML_gallocr_alloc_graph extends MustCheck { GGML_gallocr_alloc_graph() { this.getName() = "ggml_gallocr_alloc_graph" } + + override string getMessage() { + result = "The return value of `" + this.getName() + "` should be checked to ensure that the buffer allocation succeeded" + } } /** @@ -35,6 +39,10 @@ class GGML_gallocr_alloc_graph extends MustCheck { */ class GGML_gallocr_reserve extends MustCheck { GGML_gallocr_reserve() { this.getName() = "ggml_gallocr_reserve" } + + override string getMessage() { + result = "The return value of `" + this.getName() + "` should be checked to ensure that the buffer allocation succeeded" + } } /** @@ -46,6 +54,10 @@ class GGML_gallocr_reserve extends MustCheck { */ class GGML_gallocr_reserve_n extends MustCheck { GGML_gallocr_reserve_n() { this.getName() = "ggml_gallocr_reserve_n" } + + override string getMessage() { + result = "The return value of `" + this.getName() + "` should be checked to ensure that the buffer allocation succeeded" + } } /** diff --git a/cpp/src/ml/ReturnValueNotChecked.ql b/cpp/src/ml/ReturnValueNotChecked.ql index 6ee4eaf..e61fce0 100644 --- a/cpp/src/ml/ReturnValueNotChecked.ql +++ b/cpp/src/ml/ReturnValueNotChecked.ql @@ -19,4 +19,4 @@ from where value.mustCheck() and not value.isChecked() select - value.getLocation(), "The return value of `" + value.getFunction() + "` is not checked" \ No newline at end of file + value.getLocation(), value.getFunction().(MustCheck).getMessage() \ No newline at end of file diff --git a/cpp/src/ml/ReturnValueNotUsed.ql b/cpp/src/ml/ReturnValueNotUsed.ql index 3bc1548..73d906b 100644 --- a/cpp/src/ml/ReturnValueNotUsed.ql +++ b/cpp/src/ml/ReturnValueNotUsed.ql @@ -18,4 +18,4 @@ from where value.mustUse() and not value.isUsed() select - value.getLocation(), "The return value of `" + value.getFunction() + "` is discarded here" \ No newline at end of file + value.getLocation(), value.getFunction().(MustUse).getMessage() \ No newline at end of file From b6d0e93aacbd4a9784f292feb9d6020dab09da1b Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 27 May 2024 16:04:21 +0200 Subject: [PATCH 14/19] Moved memory modelling libraries to trailofbits/common --- cpp/lib/trailofbits/{ml => }/common.qll | 0 .../{ml => }/common/CustomAllocator.qll | 3 +- .../{ml => }/common/EscapeAnalysis.qll | 0 .../{ml => }/common/MethodCall.qll | 0 .../{ml => }/common/ReturnValue.qll | 85 ++++++++++++------- cpp/src/ml/LocalMemoryLeak.ql | 2 +- cpp/src/ml/LocalUseAfterFree.ql | 2 +- cpp/src/ml/ReturnValueNotChecked.ql | 4 +- cpp/src/ml/ReturnValueNotUsed.ql | 2 +- cpp/src/ml/UnnecessaryNullCheck.ql | 29 +++++++ .../CustomAllocator/CustomAllocator.expected | 0 .../CustomAllocator/CustomAllocator.ql | 2 +- .../{ml => common}/CustomAllocator/test.c | 0 .../EscapeAnalysis/EscapeAnalysis.expected | 0 .../EscapeAnalysis/EscapeAnalysis.ql | 2 +- .../{ml => common}/EscapeAnalysis/test.cpp | 0 16 files changed, 93 insertions(+), 38 deletions(-) rename cpp/lib/trailofbits/{ml => }/common.qll (100%) rename cpp/lib/trailofbits/{ml => }/common/CustomAllocator.qll (99%) rename cpp/lib/trailofbits/{ml => }/common/EscapeAnalysis.qll (100%) rename cpp/lib/trailofbits/{ml => }/common/MethodCall.qll (100%) rename cpp/lib/trailofbits/{ml => }/common/ReturnValue.qll (51%) create mode 100644 cpp/src/ml/UnnecessaryNullCheck.ql rename cpp/test/library-tests/{ml => common}/CustomAllocator/CustomAllocator.expected (100%) rename cpp/test/library-tests/{ml => common}/CustomAllocator/CustomAllocator.ql (94%) rename cpp/test/library-tests/{ml => common}/CustomAllocator/test.c (100%) rename cpp/test/library-tests/{ml => common}/EscapeAnalysis/EscapeAnalysis.expected (100%) rename cpp/test/library-tests/{ml => common}/EscapeAnalysis/EscapeAnalysis.ql (84%) rename cpp/test/library-tests/{ml => common}/EscapeAnalysis/test.cpp (100%) diff --git a/cpp/lib/trailofbits/ml/common.qll b/cpp/lib/trailofbits/common.qll similarity index 100% rename from cpp/lib/trailofbits/ml/common.qll rename to cpp/lib/trailofbits/common.qll diff --git a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll b/cpp/lib/trailofbits/common/CustomAllocator.qll similarity index 99% rename from cpp/lib/trailofbits/ml/common/CustomAllocator.qll rename to cpp/lib/trailofbits/common/CustomAllocator.qll index 8d829db..5b3ab9f 100644 --- a/cpp/lib/trailofbits/ml/common/CustomAllocator.qll +++ b/cpp/lib/trailofbits/common/CustomAllocator.qll @@ -1,7 +1,6 @@ import cpp import ReturnValue - -import trailofbits.ml.libraries +import EscapeAnalysis private import semmle.code.cpp.controlflow.Nullness private import semmle.code.cpp.dataflow.new.DataFlow diff --git a/cpp/lib/trailofbits/ml/common/EscapeAnalysis.qll b/cpp/lib/trailofbits/common/EscapeAnalysis.qll similarity index 100% rename from cpp/lib/trailofbits/ml/common/EscapeAnalysis.qll rename to cpp/lib/trailofbits/common/EscapeAnalysis.qll diff --git a/cpp/lib/trailofbits/ml/common/MethodCall.qll b/cpp/lib/trailofbits/common/MethodCall.qll similarity index 100% rename from cpp/lib/trailofbits/ml/common/MethodCall.qll rename to cpp/lib/trailofbits/common/MethodCall.qll diff --git a/cpp/lib/trailofbits/ml/common/ReturnValue.qll b/cpp/lib/trailofbits/common/ReturnValue.qll similarity index 51% rename from cpp/lib/trailofbits/ml/common/ReturnValue.qll rename to cpp/lib/trailofbits/common/ReturnValue.qll index 19a8143..9ecce24 100644 --- a/cpp/lib/trailofbits/ml/common/ReturnValue.qll +++ b/cpp/lib/trailofbits/common/ReturnValue.qll @@ -28,6 +28,11 @@ abstract class MustCheck extends Function { } } +/** + * Identifies functions that return a pointer guaranteed not to be `NULL`. + */ +abstract class NotNull extends Function { } + /** * The return value of a function. */ @@ -38,6 +43,7 @@ class ReturnValue extends FunctionCall { Function getFunction() { result = this.getTarget() } + /** * True if the return value must be used. */ @@ -52,53 +58,74 @@ class ReturnValue extends FunctionCall { this.getTarget() instanceof MustCheck } + /** + * True if the return value is a pointer guaranteed not to be `NULL`. + */ + predicate notNull() { + this.getTarget() instanceof NotNull + } + /** * Returns true if the corresponding function call is not an expression - * statement. + * statement. This means that the return value may be assigned to a variable, + * but this variable may be unused. */ predicate isUsed() { not exists(ExprStmt stmt | this = stmt.getExpr()) } /** - * Returns true if the return value flows into a conditional statement or - * expression, or a return statement. + * Returns true if the return value flows into the condition of a conditional + * statement or a conditional expression represented by the given control-flow + * node. */ - predicate isChecked() { + predicate isCheckedAt(ControlFlowNode node) { // The return value flows into the condition of an if-statement. - exists (IfStmt is | - DataFlow::localFlow( + DataFlow::localFlow( DataFlow::exprNode(this), - DataFlow::exprNode(is.getCondition().getAChild*()) - ) + DataFlow::exprNode(node.(IfStmt).getCondition().getAChild*()) ) or // The return value flows into the condition of a while-statement. - exists (WhileStmt ws | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(ws.getCondition().getAChild*()) - ) + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(node.(WhileStmt).getCondition().getAChild*()) ) or // The return value flows into the condition of a switch-statement. - exists (SwitchStmt ss | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(ss.getExpr().getAChild*()) - ) + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(node.(SwitchStmt).getExpr().getAChild*()) ) or // The return value flows into a conditional expression. - exists (ConditionalExpr ce | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(ce.getCondition().getAChild*()) - ) - ) or + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(node.(ConditionalExpr).getCondition().getAChild*()) + ) + } + + /** + * Returns true if the return value flows into the condition of a conditional + * statement or a conditional expression. + */ + predicate isChecked() { + isCheckedAt(_) + } + + /** + * True if the return value flows to a return value of the calling function, + * represented by the given control-flow node. + */ + predicate isReturnedAt(ControlFlowNode node) { // The return value is returned by the function. - exists (ReturnStmt rs | - DataFlow::localFlow( - DataFlow::exprNode(this), - DataFlow::exprNode(rs.getExpr().getAChild*()) - ) + DataFlow::localFlow( + DataFlow::exprNode(this), + DataFlow::exprNode(node.(ReturnStmt).getExpr().getAChild*()) ) } + + /** + * True if the return value flows to a return value of the calling function. + */ + predicate isReturned() { + isReturnedAt(_) + } } diff --git a/cpp/src/ml/LocalMemoryLeak.ql b/cpp/src/ml/LocalMemoryLeak.ql index 9309a97..8589354 100644 --- a/cpp/src/ml/LocalMemoryLeak.ql +++ b/cpp/src/ml/LocalMemoryLeak.ql @@ -10,7 +10,7 @@ */ import cpp -import trailofbits.ml.common +import trailofbits.common import trailofbits.ml.libraries string toLine(ControlFlowNode node) { result = node.getLocation().getStartLine().toString() } diff --git a/cpp/src/ml/LocalUseAfterFree.ql b/cpp/src/ml/LocalUseAfterFree.ql index ddebb03..934fc62 100644 --- a/cpp/src/ml/LocalUseAfterFree.ql +++ b/cpp/src/ml/LocalUseAfterFree.ql @@ -10,7 +10,7 @@ */ import cpp -import trailofbits.ml.common +import trailofbits.common import trailofbits.ml.libraries string toLine(ControlFlowNode node) { result = node.getLocation().getStartLine().toString() } diff --git a/cpp/src/ml/ReturnValueNotChecked.ql b/cpp/src/ml/ReturnValueNotChecked.ql index e61fce0..6c96540 100644 --- a/cpp/src/ml/ReturnValueNotChecked.ql +++ b/cpp/src/ml/ReturnValueNotChecked.ql @@ -10,13 +10,13 @@ */ import cpp -import trailofbits.ml.common +import trailofbits.common import trailofbits.ml.libraries from ReturnValue value where - value.mustCheck() and not value.isChecked() + value.mustCheck() and not (value.isChecked() or value.isReturned()) select value.getLocation(), value.getFunction().(MustCheck).getMessage() \ No newline at end of file diff --git a/cpp/src/ml/ReturnValueNotUsed.ql b/cpp/src/ml/ReturnValueNotUsed.ql index 73d906b..4bf6195 100644 --- a/cpp/src/ml/ReturnValueNotUsed.ql +++ b/cpp/src/ml/ReturnValueNotUsed.ql @@ -10,7 +10,7 @@ */ import cpp -import trailofbits.ml.common +import trailofbits.common import trailofbits.ml.libraries from diff --git a/cpp/src/ml/UnnecessaryNullCheck.ql b/cpp/src/ml/UnnecessaryNullCheck.ql new file mode 100644 index 0000000..805e15d --- /dev/null +++ b/cpp/src/ml/UnnecessaryNullCheck.ql @@ -0,0 +1,29 @@ +/** + * @name Unnecessary NULL check + * @id tob/cpp/ggml-unnecessary-null-check + * @description The return value from this function is guaranteed not to be `NULL` + * @kind problem + * @tags correctness ml + * @problem.severity warning + * @precision medium + * @group ml + */ + +import cpp +import trailofbits.common +import trailofbits.ml.libraries + +string toMessage(ReturnValue value) { + result = + "This check could be removed since the return value of `" + + value.getFunction() + + "` is guaranteed to be non-null" +} + +from + ControlFlowNode node, + ReturnValue value +where + value.notNull() and value.isCheckedAt(node) +select + node.getLocation(), toMessage(value) \ No newline at end of file diff --git a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected b/cpp/test/library-tests/common/CustomAllocator/CustomAllocator.expected similarity index 100% rename from cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.expected rename to cpp/test/library-tests/common/CustomAllocator/CustomAllocator.expected diff --git a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql b/cpp/test/library-tests/common/CustomAllocator/CustomAllocator.ql similarity index 94% rename from cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql rename to cpp/test/library-tests/common/CustomAllocator/CustomAllocator.ql index bcedf80..faa4a1d 100644 --- a/cpp/test/library-tests/ml/CustomAllocator/CustomAllocator.ql +++ b/cpp/test/library-tests/common/CustomAllocator/CustomAllocator.ql @@ -1,5 +1,5 @@ import cpp -import trailofbits.ml.common +import trailofbits.common import trailofbits.ml.libraries from diff --git a/cpp/test/library-tests/ml/CustomAllocator/test.c b/cpp/test/library-tests/common/CustomAllocator/test.c similarity index 100% rename from cpp/test/library-tests/ml/CustomAllocator/test.c rename to cpp/test/library-tests/common/CustomAllocator/test.c diff --git a/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.expected b/cpp/test/library-tests/common/EscapeAnalysis/EscapeAnalysis.expected similarity index 100% rename from cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.expected rename to cpp/test/library-tests/common/EscapeAnalysis/EscapeAnalysis.expected diff --git a/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql b/cpp/test/library-tests/common/EscapeAnalysis/EscapeAnalysis.ql similarity index 84% rename from cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql rename to cpp/test/library-tests/common/EscapeAnalysis/EscapeAnalysis.ql index 893555b..195e6ac 100644 --- a/cpp/test/library-tests/ml/EscapeAnalysis/EscapeAnalysis.ql +++ b/cpp/test/library-tests/common/EscapeAnalysis/EscapeAnalysis.ql @@ -1,5 +1,5 @@ import cpp -import trailofbits.ml.common +import trailofbits.common from ControlFlowNode node, diff --git a/cpp/test/library-tests/ml/EscapeAnalysis/test.cpp b/cpp/test/library-tests/common/EscapeAnalysis/test.cpp similarity index 100% rename from cpp/test/library-tests/ml/EscapeAnalysis/test.cpp rename to cpp/test/library-tests/common/EscapeAnalysis/test.cpp From e0ab14b25b0dcc0fe2da5a8cdf19a8dae8731159 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Mon, 27 May 2024 16:31:53 +0200 Subject: [PATCH 15/19] Added auto-generated QL libraries for GGML header files --- cpp/lib/trailofbits/ml/ggml/ggml.qll | 1502 +++++++++++++++++- cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll | 133 +- cpp/lib/trailofbits/ml/ggml/ggml_backend.qll | 859 +++++++++- 3 files changed, 2372 insertions(+), 122 deletions(-) diff --git a/cpp/lib/trailofbits/ml/ggml/ggml.qll b/cpp/lib/trailofbits/ml/ggml/ggml.qll index d9fd283..10b26fb 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml.qll @@ -1,4 +1,361 @@ -import trailofbits.ml.common +// ********************************************************************* +// +// This library has been automatically generated using the Busy Work +// VSCode extension from the file 'ggml.h'. +// +// ********************************************************************* +import cpp +import trailofbits.common + +// ********************************************************************* +// +// Function types matching the individual functions defined by +// 'ggml.h'. +// +// ********************************************************************* + +/** + * GGML_API float ggml_fp16_to_fp32(ggml_fp16_t x); + */ +class GGML_fp16_to_fp32 extends MustUse { + GGML_fp16_to_fp32() { + this.getName() = "ggml_fp16_to_fp32" + } +} + +/** + * GGML_API ggml_fp16_t ggml_fp32_to_fp16(float x); + */ +class GGML_fp32_to_fp16 extends MustUse { + GGML_fp32_to_fp16() { + this.getName() = "ggml_fp32_to_fp16" + } +} + +/** + * GGML_API void ggml_fp16_to_fp32_row( + * const ggml_fp16_t * x, + * float * y, + * int64_t n + * ); + */ +class GGML_fp16_to_fp32_row extends Function { + GGML_fp16_to_fp32_row() { + this.getName() = "ggml_fp16_to_fp32_row" + } +} + +/** + * GGML_API void ggml_fp32_to_fp16_row( + * const float * x, + * ggml_fp16_t * y, + * int64_t n + * ); + */ +class GGML_fp32_to_fp16_row extends Function { + GGML_fp32_to_fp16_row() { + this.getName() = "ggml_fp32_to_fp16_row" + } +} + +/** + * GGML_API bool ggml_guid_matches(ggml_guid_t guid_a, ggml_guid_t guid_b); + */ +class GGML_guid_matches extends MustUse { + GGML_guid_matches() { + this.getName() = "ggml_guid_matches" + } +} + +/** + * GGML_API void ggml_time_init(void); + */ +class GGML_time_init extends Function { + GGML_time_init() { + this.getName() = "ggml_time_init" + } +} + +/** + * GGML_API int64_t ggml_time_ms(void); + */ +class GGML_time_ms extends MustUse { + GGML_time_ms() { + this.getName() = "ggml_time_ms" + } +} + +/** + * GGML_API int64_t ggml_time_us(void); + */ +class GGML_time_us extends MustUse { + GGML_time_us() { + this.getName() = "ggml_time_us" + } +} + +/** + * GGML_API int64_t ggml_cycles(void); + */ +class GGML_cycles extends MustUse { + GGML_cycles() { + this.getName() = "ggml_cycles" + } +} + +/** + * GGML_API int64_t ggml_cycles_per_ms(void); + */ +class GGML_cycles_per_ms extends MustUse { + GGML_cycles_per_ms() { + this.getName() = "ggml_cycles_per_ms" + } +} + +/** + * GGML_API void ggml_print_backtrace(void); + */ +class GGML_print_backtrace extends Function { + GGML_print_backtrace() { + this.getName() = "ggml_print_backtrace" + } +} + +/** + * GGML_API void ggml_numa_init(enum ggml_numa_strategy numa); + */ +class GGML_numa_init extends Function { + GGML_numa_init() { + this.getName() = "ggml_numa_init" + } +} + +/** + * GGML_API bool ggml_is_numa(void); + */ +class GGML_is_numa extends MustUse { + GGML_is_numa() { + this.getName() = "ggml_is_numa" + } +} + +/** + * GGML_API void ggml_print_object (const struct ggml_object * obj); + */ +class GGML_print_object extends Function { + GGML_print_object() { + this.getName() = "ggml_print_object" + } +} + +/** + * GGML_API void ggml_print_objects(const struct ggml_context * ctx); + */ +class GGML_print_objects extends Function { + GGML_print_objects() { + this.getName() = "ggml_print_objects" + } +} + +/** + * GGML_API GGML_CALL int64_t ggml_nelements ( + * const struct ggml_tensor * tensor + * ); + */ +class GGML_nelements extends MustUse { + GGML_nelements() { + this.getName() = "ggml_nelements" + } +} + +/** + * GGML_API GGML_CALL int64_t ggml_nrows (const struct ggml_tensor * tensor); + */ +class GGML_nrows extends MustUse { + GGML_nrows() { + this.getName() = "ggml_nrows" + } +} + +/** + * GGML_API GGML_CALL size_t ggml_nbytes (const struct ggml_tensor * tensor); + */ +class GGML_nbytes extends MustUse { + GGML_nbytes() { + this.getName() = "ggml_nbytes" + } +} + +/** + * GGML_API size_t ggml_nbytes_pad (const struct ggml_tensor * tensor); + */ +class GGML_nbytes_pad extends MustUse { + GGML_nbytes_pad() { + this.getName() = "ggml_nbytes_pad" + } +} + +/** + * GGML_API GGML_CALL int ggml_blck_size(enum ggml_type type); + */ +class GGML_blck_size extends MustUse { + GGML_blck_size() { + this.getName() = "ggml_blck_size" + } +} + +/** + * GGML_API GGML_CALL size_t ggml_type_size(enum ggml_type type); + */ +class GGML_type_size extends MustUse { + GGML_type_size() { + this.getName() = "ggml_type_size" + } +} + +/** + * GGML_API GGML_CALL size_t ggml_row_size (enum ggml_type type, int64_t ne); + */ +class GGML_row_size extends MustUse { + GGML_row_size() { + this.getName() = "ggml_row_size" + } +} + +/** + * GGML_API GGML_CALL size_t ggml_element_size( + * const struct ggml_tensor * tensor + * ); + */ +class GGML_element_size extends MustUse { + GGML_element_size() { + this.getName() = "ggml_element_size" + } +} + +/** + * GGML_API GGML_CALL bool ggml_is_quantized(enum ggml_type type); + */ +class GGML_is_quantized extends MustUse { + GGML_is_quantized() { + this.getName() = "ggml_is_quantized" + } +} + +/** + * GGML_API enum ggml_type ggml_ftype_to_ggml_type(enum ggml_ftype ftype); + */ +class GGML_ftype_to_ggml_type extends MustUse { + GGML_ftype_to_ggml_type() { + this.getName() = "ggml_ftype_to_ggml_type" + } +} + +/** + * GGML_API GGML_CALL bool ggml_is_transposed( + * const struct ggml_tensor * tensor + * ); + */ +class GGML_is_transposed extends MustUse { + GGML_is_transposed() { + this.getName() = "ggml_is_transposed" + } +} + +/** + * GGML_API GGML_CALL bool ggml_is_contiguous( + * const struct ggml_tensor * tensor + * ); + */ +class GGML_is_contiguous extends MustUse { + GGML_is_contiguous() { + this.getName() = "ggml_is_contiguous" + } +} + +/** + * GGML_API GGML_CALL bool ggml_is_permuted (const struct ggml_tensor * tensor); + */ +class GGML_is_permuted extends MustUse { + GGML_is_permuted() { + this.getName() = "ggml_is_permuted" + } +} + +/** + * GGML_API GGML_CALL bool ggml_is_empty (const struct ggml_tensor * tensor); + */ +class GGML_is_empty extends MustUse { + GGML_is_empty() { + this.getName() = "ggml_is_empty" + } +} + +/** + * GGML_API bool ggml_is_scalar (const struct ggml_tensor * tensor); + */ +class GGML_is_scalar extends MustUse { + GGML_is_scalar() { + this.getName() = "ggml_is_scalar" + } +} + +/** + * GGML_API bool ggml_is_vector (const struct ggml_tensor * tensor); + */ +class GGML_is_vector extends MustUse { + GGML_is_vector() { + this.getName() = "ggml_is_vector" + } +} + +/** + * GGML_API bool ggml_is_matrix (const struct ggml_tensor * tensor); + */ +class GGML_is_matrix extends MustUse { + GGML_is_matrix() { + this.getName() = "ggml_is_matrix" + } +} + +/** + * GGML_API bool ggml_is_3d (const struct ggml_tensor * tensor); + */ +class GGML_is_3d extends MustUse { + GGML_is_3d() { + this.getName() = "ggml_is_3d" + } +} + +/** + * GGML_API int ggml_n_dims (const struct ggml_tensor * tensor); + */ +class GGML_n_dims extends MustUse { + GGML_n_dims() { + this.getName() = "ggml_n_dims" + } +} + +/** + * GGML_API bool ggml_are_same_shape( + * const struct ggml_tensor * t0, + * const struct ggml_tensor * t1 + * ); + */ +class GGML_are_same_shape extends MustUse { + GGML_are_same_shape() { + this.getName() = "ggml_are_same_shape" + } +} + +/** + * GGML_API size_t ggml_tensor_overhead(void); + */ +class GGML_tensor_overhead extends MustUse { + GGML_tensor_overhead() { + this.getName() = "ggml_tensor_overhead" + } +} /** * struct ggml_context * ggml_init(struct ggml_init_params params); @@ -10,7 +367,7 @@ class GGML_init extends Alloc { } /** - * void ggml_free(struct ggml_context * ctx); + * GGML_API void ggml_free(struct ggml_context * ctx); */ class GGML_free extends Free { GGML_free() { @@ -19,35 +376,1148 @@ class GGML_free extends Free { } /** - * GGML_API struct gguf_context * gguf_init_empty(void); + * GGML_API size_t ggml_used_mem(const struct ggml_context * ctx); */ -class GGUF_init_empty extends Alloc { - GGUF_init_empty() { - this.getName() = "gguf_init_empty" +class GGML_used_mem extends MustUse { + GGML_used_mem() { + this.getName() = "ggml_used_mem" } } /** - * GGML_API struct gguf_context * gguf_init_from_file( - * const char * fname, - * struct gguf_init_params params + * GGML_API size_t ggml_set_scratch ( + * struct ggml_context * ctx, + * struct ggml_scratch scratch * ); */ -class GGUF_init_from_file extends Alloc { - GGUF_init_from_file() { - this.getName() = "gguf_init_from_file" +class GGML_set_scratch extends MustUse { + GGML_set_scratch() { + this.getName() = "ggml_set_scratch" } } /** - * GGML_API void gguf_free(struct gguf_context * ctx); + * GGML_API bool ggml_get_no_alloc(struct ggml_context * ctx); */ -class GGUF_free extends Free { - GGUF_free() { - this.getName() = "gguf_free" +class GGML_get_no_alloc extends MustUse { + GGML_get_no_alloc() { + this.getName() = "ggml_get_no_alloc" + } +} + +/** + * GGML_API void ggml_set_no_alloc(struct ggml_context * ctx, bool no_alloc); + */ +class GGML_set_no_alloc extends Function { + GGML_set_no_alloc() { + this.getName() = "ggml_set_no_alloc" + } +} + +/** + * GGML_API size_t ggml_get_mem_size (const struct ggml_context * ctx); + */ +class GGML_get_mem_size extends MustUse { + GGML_get_mem_size() { + this.getName() = "ggml_get_mem_size" + } +} + +/** + * GGML_API size_t ggml_get_max_tensor_size(const struct ggml_context * ctx); + */ +class GGML_get_max_tensor_size extends MustUse { + GGML_get_max_tensor_size() { + this.getName() = "ggml_get_max_tensor_size" + } +} + +/** + * GGML_API void ggml_unravel_index( + * const struct ggml_tensor * tensor, + * int64_t i, + * int64_t * i0, + * int64_t * i1, + * int64_t * i2, + * int64_t * i3 + * ); + */ +class GGML_unravel_index extends Function { + GGML_unravel_index() { + this.getName() = "ggml_unravel_index" + } +} + +/** + * GGML_API int32_t ggml_get_i32_1d(const struct ggml_tensor * tensor, int i); + */ +class GGML_get_i32_1d extends MustUse { + GGML_get_i32_1d() { + this.getName() = "ggml_get_i32_1d" + } +} + +/** + * GGML_API void ggml_set_i32_1d( + * const struct ggml_tensor * tensor, + * int i, + * int32_t value + * ); + */ +class GGML_set_i32_1d extends Function { + GGML_set_i32_1d() { + this.getName() = "ggml_set_i32_1d" + } +} + +/** + * GGML_API int32_t ggml_get_i32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3 + * ); + */ +class GGML_get_i32_nd extends MustUse { + GGML_get_i32_nd() { + this.getName() = "ggml_get_i32_nd" } } +/** + * GGML_API void ggml_set_i32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3, + * int32_t value + * ); + */ +class GGML_set_i32_nd extends Function { + GGML_set_i32_nd() { + this.getName() = "ggml_set_i32_nd" + } +} + +/** + * GGML_API float ggml_get_f32_1d(const struct ggml_tensor * tensor, int i); + */ +class GGML_get_f32_1d extends MustUse { + GGML_get_f32_1d() { + this.getName() = "ggml_get_f32_1d" + } +} + +/** + * GGML_API void ggml_set_f32_1d( + * const struct ggml_tensor * tensor, + * int i, + * float value + * ); + */ +class GGML_set_f32_1d extends Function { + GGML_set_f32_1d() { + this.getName() = "ggml_set_f32_1d" + } +} + +/** + * GGML_API float ggml_get_f32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3 + * ); + */ +class GGML_get_f32_nd extends MustUse { + GGML_get_f32_nd() { + this.getName() = "ggml_get_f32_nd" + } +} + +/** + * GGML_API void ggml_set_f32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3, + * float value + * ); + */ +class GGML_set_f32_nd extends Function { + GGML_set_f32_nd() { + this.getName() = "ggml_set_f32_nd" + } +} + +/** + * GGML_API GGML_CALL enum ggml_unary_op ggml_get_unary_op( + * const struct ggml_tensor * tensor + * ); + */ +class GGML_get_unary_op extends MustUse { + GGML_get_unary_op() { + this.getName() = "ggml_get_unary_op" + } +} + +/** + * GGML_API void ggml_mul_mat_set_prec( + * struct ggml_tensor * a, + * enum ggml_prec prec + * ); + */ +class GGML_mul_mat_set_prec extends Function { + GGML_mul_mat_set_prec() { + this.getName() = "ggml_mul_mat_set_prec" + } +} + +/** + * GGML_CALL void ggml_rope_yarn_corr_dims( + * int n_dims, + * int n_orig_ctx, + * float freq_base, + * float beta_fast, + * float beta_slow, + * float dims[2] + * ); + */ +class GGML_rope_yarn_corr_dims extends Function { + GGML_rope_yarn_corr_dims() { + this.getName() = "ggml_rope_yarn_corr_dims" + } +} + +/** + * GGML_API struct ggml_opt_params ggml_opt_default_params( + * enum ggml_opt_type type + * ); + */ +class GGML_opt_default_params extends MustUse { + GGML_opt_default_params() { + this.getName() = "ggml_opt_default_params" + } +} + +/** + * GGML_API enum ggml_opt_result ggml_opt( + * struct ggml_context * ctx, + * struct ggml_opt_params params, + * struct ggml_tensor * f + * ); + */ +class GGML_opt extends MustUse { + GGML_opt() { + this.getName() = "ggml_opt" + } +} + +/** + * GGML_API void ggml_opt_init( + * struct ggml_context * ctx, + * struct ggml_opt_context * opt, + * struct ggml_opt_params params, + * int64_t nx + * ); + */ +class GGML_opt_init extends Function { + GGML_opt_init() { + this.getName() = "ggml_opt_init" + } +} + +/** + * GGML_API enum ggml_opt_result ggml_opt_resume( + * struct ggml_context * ctx, + * struct ggml_opt_context * opt, + * struct ggml_tensor * f + * ); + */ +class GGML_opt_resume extends MustUse { + GGML_opt_resume() { + this.getName() = "ggml_opt_resume" + } +} + +/** + * GGML_API enum ggml_opt_result ggml_opt_resume_g( + * struct ggml_context * ctx, + * struct ggml_opt_context * opt, + * struct ggml_tensor * f, + * struct ggml_cgraph * gf, + * struct ggml_cgraph * gb, + * ggml_opt_callback callback, + * void * callback_data + * ); + */ +class GGML_opt_resume_g extends MustUse { + GGML_opt_resume_g() { + this.getName() = "ggml_opt_resume_g" + } +} + +/** + * GGML_API void ggml_set_input(struct ggml_tensor * tensor); + */ +class GGML_set_input extends Function { + GGML_set_input() { + this.getName() = "ggml_set_input" + } +} + +/** + * GGML_API void ggml_set_output(struct ggml_tensor * tensor); + */ +class GGML_set_output extends Function { + GGML_set_output() { + this.getName() = "ggml_set_output" + } +} + +/** + * GGML_API void ggml_quantize_init(enum ggml_type type); + */ +class GGML_quantize_init extends Function { + GGML_quantize_init() { + this.getName() = "ggml_quantize_init" + } +} + +/** + * GGML_API void ggml_quantize_free(void); + */ +class GGML_quantize_free extends Function { + GGML_quantize_free() { + this.getName() = "ggml_quantize_free" + } +} + +/** + * GGML_API bool ggml_quantize_requires_imatrix(enum ggml_type type); + */ +class GGML_quantize_requires_imatrix extends MustUse { + GGML_quantize_requires_imatrix() { + this.getName() = "ggml_quantize_requires_imatrix" + } +} + +/** + * GGML_API size_t ggml_quantize_chunk( + * enum ggml_type type, + * const float * src, + * void * dst, + * int64_t start, + * int64_t nrows, + * int64_t n_per_row, + * const float * imatrix + * ); + */ +class GGML_quantize_chunk extends MustUse { + GGML_quantize_chunk() { + this.getName() = "ggml_quantize_chunk" + } +} + +/** + * GGML_API struct gguf_context * gguf_init_empty(void); + */ +class GGUF_init_empty extends Alloc { + GGUF_init_empty() { + this.getName() = "gguf_init_empty" + } +} + +/** + * GGML_API struct gguf_context * gguf_init_from_file( + * const char * fname, + * struct gguf_init_params params + * ); + */ +class GGUF_init_from_file extends Alloc { + GGUF_init_from_file() { + this.getName() = "gguf_init_from_file" + } +} + +/** + * GGML_API void gguf_free(struct gguf_context * ctx); + */ +class GGUF_free extends Free { + GGUF_free() { + this.getName() = "gguf_free" + } +} + +/** + * GGML_API int gguf_get_version (const struct gguf_context * ctx); + */ +class GGUF_get_version extends MustUse { + GGUF_get_version() { + this.getName() = "gguf_get_version" + } +} + +/** + * GGML_API size_t gguf_get_alignment (const struct gguf_context * ctx); + */ +class GGUF_get_alignment extends MustUse { + GGUF_get_alignment() { + this.getName() = "gguf_get_alignment" + } +} + +/** + * GGML_API size_t gguf_get_data_offset(const struct gguf_context * ctx); + */ +class GGUF_get_data_offset extends MustUse { + GGUF_get_data_offset() { + this.getName() = "gguf_get_data_offset" + } +} + +/** + * GGML_API int gguf_get_n_kv(const struct gguf_context * ctx); + */ +class GGUF_get_n_kv extends MustUse { + GGUF_get_n_kv() { + this.getName() = "gguf_get_n_kv" + } +} + +/** + * GGML_API int gguf_find_key( + * const struct gguf_context * ctx, + * const char * key + * ); + */ +class GGUF_find_key extends MustUse { + GGUF_find_key() { + this.getName() = "gguf_find_key" + } +} + +/** + * GGML_API enum gguf_type gguf_get_kv_type ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_kv_type extends MustUse { + GGUF_get_kv_type() { + this.getName() = "gguf_get_kv_type" + } +} + +/** + * GGML_API enum gguf_type gguf_get_arr_type( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_arr_type extends MustUse { + GGUF_get_arr_type() { + this.getName() = "gguf_get_arr_type" + } +} + +/** + * GGML_API uint8_t gguf_get_val_u8 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_u8 extends MustUse { + GGUF_get_val_u8() { + this.getName() = "gguf_get_val_u8" + } +} + +/** + * GGML_API int8_t gguf_get_val_i8 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_i8 extends MustUse { + GGUF_get_val_i8() { + this.getName() = "gguf_get_val_i8" + } +} + +/** + * GGML_API uint16_t gguf_get_val_u16 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_u16 extends MustUse { + GGUF_get_val_u16() { + this.getName() = "gguf_get_val_u16" + } +} + +/** + * GGML_API int16_t gguf_get_val_i16 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_i16 extends MustUse { + GGUF_get_val_i16() { + this.getName() = "gguf_get_val_i16" + } +} + +/** + * GGML_API uint32_t gguf_get_val_u32 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_u32 extends MustUse { + GGUF_get_val_u32() { + this.getName() = "gguf_get_val_u32" + } +} + +/** + * GGML_API int32_t gguf_get_val_i32 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_i32 extends MustUse { + GGUF_get_val_i32() { + this.getName() = "gguf_get_val_i32" + } +} + +/** + * GGML_API float gguf_get_val_f32 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_f32 extends MustUse { + GGUF_get_val_f32() { + this.getName() = "gguf_get_val_f32" + } +} + +/** + * GGML_API uint64_t gguf_get_val_u64 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_u64 extends MustUse { + GGUF_get_val_u64() { + this.getName() = "gguf_get_val_u64" + } +} + +/** + * GGML_API int64_t gguf_get_val_i64 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_i64 extends MustUse { + GGUF_get_val_i64() { + this.getName() = "gguf_get_val_i64" + } +} + +/** + * GGML_API double gguf_get_val_f64 ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_f64 extends MustUse { + GGUF_get_val_f64() { + this.getName() = "gguf_get_val_f64" + } +} + +/** + * GGML_API bool gguf_get_val_bool(const struct gguf_context * ctx, int key_id); + */ +class GGUF_get_val_bool extends MustUse { + GGUF_get_val_bool() { + this.getName() = "gguf_get_val_bool" + } +} + +/** + * GGML_API int gguf_get_arr_n (const struct gguf_context * ctx, int key_id); + */ +class GGUF_get_arr_n extends MustUse { + GGUF_get_arr_n() { + this.getName() = "gguf_get_arr_n" + } +} + +/** + * GGML_API int gguf_get_n_tensors (const struct gguf_context * ctx); + */ +class GGUF_get_n_tensors extends MustUse { + GGUF_get_n_tensors() { + this.getName() = "gguf_get_n_tensors" + } +} + +/** + * GGML_API int gguf_find_tensor ( + * const struct gguf_context * ctx, + * const char * name + * ); + */ +class GGUF_find_tensor extends MustUse { + GGUF_find_tensor() { + this.getName() = "gguf_find_tensor" + } +} + +/** + * GGML_API size_t gguf_get_tensor_offset( + * const struct gguf_context * ctx, + * int i + * ); + */ +class GGUF_get_tensor_offset extends MustUse { + GGUF_get_tensor_offset() { + this.getName() = "gguf_get_tensor_offset" + } +} + +/** + * GGML_API enum ggml_type gguf_get_tensor_type ( + * const struct gguf_context * ctx, + * int i + * ); + */ +class GGUF_get_tensor_type extends MustUse { + GGUF_get_tensor_type() { + this.getName() = "gguf_get_tensor_type" + } +} + +/** + * GGML_API void gguf_set_val_u8 ( + * struct gguf_context * ctx, + * const char * key, + * uint8_t val + * ); + */ +class GGUF_set_val_u8 extends Function { + GGUF_set_val_u8() { + this.getName() = "gguf_set_val_u8" + } +} + +/** + * GGML_API void gguf_set_val_i8 ( + * struct gguf_context * ctx, + * const char * key, + * int8_t val + * ); + */ +class GGUF_set_val_i8 extends Function { + GGUF_set_val_i8() { + this.getName() = "gguf_set_val_i8" + } +} + +/** + * GGML_API void gguf_set_val_u16 ( + * struct gguf_context * ctx, + * const char * key, + * uint16_t val + * ); + */ +class GGUF_set_val_u16 extends Function { + GGUF_set_val_u16() { + this.getName() = "gguf_set_val_u16" + } +} + +/** + * GGML_API void gguf_set_val_i16 ( + * struct gguf_context * ctx, + * const char * key, + * int16_t val + * ); + */ +class GGUF_set_val_i16 extends Function { + GGUF_set_val_i16() { + this.getName() = "gguf_set_val_i16" + } +} + +/** + * GGML_API void gguf_set_val_u32 ( + * struct gguf_context * ctx, + * const char * key, + * uint32_t val + * ); + */ +class GGUF_set_val_u32 extends Function { + GGUF_set_val_u32() { + this.getName() = "gguf_set_val_u32" + } +} + +/** + * GGML_API void gguf_set_val_i32 ( + * struct gguf_context * ctx, + * const char * key, + * int32_t val + * ); + */ +class GGUF_set_val_i32 extends Function { + GGUF_set_val_i32() { + this.getName() = "gguf_set_val_i32" + } +} + +/** + * GGML_API void gguf_set_val_f32 ( + * struct gguf_context * ctx, + * const char * key, + * float val + * ); + */ +class GGUF_set_val_f32 extends Function { + GGUF_set_val_f32() { + this.getName() = "gguf_set_val_f32" + } +} + +/** + * GGML_API void gguf_set_val_u64 ( + * struct gguf_context * ctx, + * const char * key, + * uint64_t val + * ); + */ +class GGUF_set_val_u64 extends Function { + GGUF_set_val_u64() { + this.getName() = "gguf_set_val_u64" + } +} + +/** + * GGML_API void gguf_set_val_i64 ( + * struct gguf_context * ctx, + * const char * key, + * int64_t val + * ); + */ +class GGUF_set_val_i64 extends Function { + GGUF_set_val_i64() { + this.getName() = "gguf_set_val_i64" + } +} + +/** + * GGML_API void gguf_set_val_f64 ( + * struct gguf_context * ctx, + * const char * key, + * double val + * ); + */ +class GGUF_set_val_f64 extends Function { + GGUF_set_val_f64() { + this.getName() = "gguf_set_val_f64" + } +} + +/** + * GGML_API void gguf_set_val_bool( + * struct gguf_context * ctx, + * const char * key, + * bool val + * ); + */ +class GGUF_set_val_bool extends Function { + GGUF_set_val_bool() { + this.getName() = "gguf_set_val_bool" + } +} + +/** + * GGML_API void gguf_set_val_str ( + * struct gguf_context * ctx, + * const char * key, + * const char * val + * ); + */ +class GGUF_set_val_str extends Function { + GGUF_set_val_str() { + this.getName() = "gguf_set_val_str" + } +} + +/** + * GGML_API void gguf_set_arr_data( + * struct gguf_context * ctx, + * const char * key, + * enum gguf_type type, + * const void * data, + * int n + * ); + */ +class GGUF_set_arr_data extends Function { + GGUF_set_arr_data() { + this.getName() = "gguf_set_arr_data" + } +} + +/** + * GGML_API void gguf_set_arr_str ( + * struct gguf_context * ctx, + * const char * key, + * const char ** data, + * int n + * ); + */ +class GGUF_set_arr_str extends Function { + GGUF_set_arr_str() { + this.getName() = "gguf_set_arr_str" + } +} + +/** + * GGML_API void gguf_set_kv( + * struct gguf_context * ctx, + * struct gguf_context * src + * ); + */ +class GGUF_set_kv extends Function { + GGUF_set_kv() { + this.getName() = "gguf_set_kv" + } +} + +/** + * GGML_API void gguf_add_tensor( + * struct gguf_context * ctx, + * const struct ggml_tensor * tensor + * ); + */ +class GGUF_add_tensor extends Function { + GGUF_add_tensor() { + this.getName() = "gguf_add_tensor" + } +} + +/** + * GGML_API void gguf_set_tensor_type( + * struct gguf_context * ctx, + * const char * name, + * enum ggml_type type + * ); + */ +class GGUF_set_tensor_type extends Function { + GGUF_set_tensor_type() { + this.getName() = "gguf_set_tensor_type" + } +} + +/** + * GGML_API void gguf_set_tensor_data( + * struct gguf_context * ctx, + * const char * name, + * const void * data, + * size_t size + * ); + */ +class GGUF_set_tensor_data extends Function { + GGUF_set_tensor_data() { + this.getName() = "gguf_set_tensor_data" + } +} + +/** + * GGML_API void gguf_write_to_file( + * const struct gguf_context * ctx, + * const char * fname, + * bool only_meta + * ); + */ +class GGUF_write_to_file extends Function { + GGUF_write_to_file() { + this.getName() = "gguf_write_to_file" + } +} + +/** + * GGML_API size_t gguf_get_meta_size(const struct gguf_context * ctx); + */ +class GGUF_get_meta_size extends MustUse { + GGUF_get_meta_size() { + this.getName() = "gguf_get_meta_size" + } +} + +/** + * GGML_API void gguf_get_meta_data( + * const struct gguf_context * ctx, + * void * data + * ); + */ +class GGUF_get_meta_data extends Function { + GGUF_get_meta_data() { + this.getName() = "gguf_get_meta_data" + } +} + +/** + * GGML_API int ggml_cpu_has_avx (void); + */ +class GGML_cpu_has_avx extends MustUse { + GGML_cpu_has_avx() { + this.getName() = "ggml_cpu_has_avx" + } +} + +/** + * GGML_API int ggml_cpu_has_avx_vnni (void); + */ +class GGML_cpu_has_avx_vnni extends MustUse { + GGML_cpu_has_avx_vnni() { + this.getName() = "ggml_cpu_has_avx_vnni" + } +} + +/** + * GGML_API int ggml_cpu_has_avx2 (void); + */ +class GGML_cpu_has_avx2 extends MustUse { + GGML_cpu_has_avx2() { + this.getName() = "ggml_cpu_has_avx2" + } +} + +/** + * GGML_API int ggml_cpu_has_avx512 (void); + */ +class GGML_cpu_has_avx512 extends MustUse { + GGML_cpu_has_avx512() { + this.getName() = "ggml_cpu_has_avx512" + } +} + +/** + * GGML_API int ggml_cpu_has_avx512_vbmi(void); + */ +class GGML_cpu_has_avx512_vbmi extends MustUse { + GGML_cpu_has_avx512_vbmi() { + this.getName() = "ggml_cpu_has_avx512_vbmi" + } +} + +/** + * GGML_API int ggml_cpu_has_avx512_vnni(void); + */ +class GGML_cpu_has_avx512_vnni extends MustUse { + GGML_cpu_has_avx512_vnni() { + this.getName() = "ggml_cpu_has_avx512_vnni" + } +} + +/** + * GGML_API int ggml_cpu_has_fma (void); + */ +class GGML_cpu_has_fma extends MustUse { + GGML_cpu_has_fma() { + this.getName() = "ggml_cpu_has_fma" + } +} + +/** + * GGML_API int ggml_cpu_has_neon (void); + */ +class GGML_cpu_has_neon extends MustUse { + GGML_cpu_has_neon() { + this.getName() = "ggml_cpu_has_neon" + } +} + +/** + * GGML_API int ggml_cpu_has_arm_fma (void); + */ +class GGML_cpu_has_arm_fma extends MustUse { + GGML_cpu_has_arm_fma() { + this.getName() = "ggml_cpu_has_arm_fma" + } +} + +/** + * GGML_API int ggml_cpu_has_metal (void); + */ +class GGML_cpu_has_metal extends MustUse { + GGML_cpu_has_metal() { + this.getName() = "ggml_cpu_has_metal" + } +} + +/** + * GGML_API int ggml_cpu_has_f16c (void); + */ +class GGML_cpu_has_f16c extends MustUse { + GGML_cpu_has_f16c() { + this.getName() = "ggml_cpu_has_f16c" + } +} + +/** + * GGML_API int ggml_cpu_has_fp16_va (void); + */ +class GGML_cpu_has_fp16_va extends MustUse { + GGML_cpu_has_fp16_va() { + this.getName() = "ggml_cpu_has_fp16_va" + } +} + +/** + * GGML_API int ggml_cpu_has_wasm_simd (void); + */ +class GGML_cpu_has_wasm_simd extends MustUse { + GGML_cpu_has_wasm_simd() { + this.getName() = "ggml_cpu_has_wasm_simd" + } +} + +/** + * GGML_API int ggml_cpu_has_blas (void); + */ +class GGML_cpu_has_blas extends MustUse { + GGML_cpu_has_blas() { + this.getName() = "ggml_cpu_has_blas" + } +} + +/** + * GGML_API int ggml_cpu_has_cuda (void); + */ +class GGML_cpu_has_cuda extends MustUse { + GGML_cpu_has_cuda() { + this.getName() = "ggml_cpu_has_cuda" + } +} + +/** + * GGML_API int ggml_cpu_has_clblast (void); + */ +class GGML_cpu_has_clblast extends MustUse { + GGML_cpu_has_clblast() { + this.getName() = "ggml_cpu_has_clblast" + } +} + +/** + * GGML_API int ggml_cpu_has_vulkan (void); + */ +class GGML_cpu_has_vulkan extends MustUse { + GGML_cpu_has_vulkan() { + this.getName() = "ggml_cpu_has_vulkan" + } +} + +/** + * GGML_API int ggml_cpu_has_kompute (void); + */ +class GGML_cpu_has_kompute extends MustUse { + GGML_cpu_has_kompute() { + this.getName() = "ggml_cpu_has_kompute" + } +} + +/** + * GGML_API int ggml_cpu_has_gpublas (void); + */ +class GGML_cpu_has_gpublas extends MustUse { + GGML_cpu_has_gpublas() { + this.getName() = "ggml_cpu_has_gpublas" + } +} + +/** + * GGML_API int ggml_cpu_has_sse3 (void); + */ +class GGML_cpu_has_sse3 extends MustUse { + GGML_cpu_has_sse3() { + this.getName() = "ggml_cpu_has_sse3" + } +} + +/** + * GGML_API int ggml_cpu_has_ssse3 (void); + */ +class GGML_cpu_has_ssse3 extends MustUse { + GGML_cpu_has_ssse3() { + this.getName() = "ggml_cpu_has_ssse3" + } +} + +/** + * GGML_API int ggml_cpu_has_sycl (void); + */ +class GGML_cpu_has_sycl extends MustUse { + GGML_cpu_has_sycl() { + this.getName() = "ggml_cpu_has_sycl" + } +} + +/** + * GGML_API int ggml_cpu_has_vsx (void); + */ +class GGML_cpu_has_vsx extends MustUse { + GGML_cpu_has_vsx() { + this.getName() = "ggml_cpu_has_vsx" + } +} + +/** + * GGML_API int ggml_cpu_has_matmul_int8(void); + */ +class GGML_cpu_has_matmul_int8 extends MustUse { + GGML_cpu_has_matmul_int8() { + this.getName() = "ggml_cpu_has_matmul_int8" + } +} + +/** + * GGML_API ggml_type_traits_t ggml_internal_get_type_traits( + * enum ggml_type type + * ); + */ +class GGML_internal_get_type_traits extends MustUse { + GGML_internal_get_type_traits() { + this.getName() = "ggml_internal_get_type_traits" + } +} + +// ********************************************************************* +// +// Custom allocators defined by 'ggml.h'. +// +// ********************************************************************* + +/** + * Alloc: + * ggml_init + * + * Free: + * ggml_free + */ class GGMLContextAllocator extends CustomAllocator { GGMLContextAllocator() { this = "GGMLContextAllocator" diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll index f599626..ab4629e 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll @@ -1,75 +1,136 @@ -import trailofbits.ml.common +// ********************************************************************* +// +// This library has been automatically generated using the Busy Work +// VSCode extension from the file 'ggml-alloc.h'. +// +// ********************************************************************* +import cpp +import trailofbits.common + +// ********************************************************************* +// +// Function types matching the individual functions defined by +// 'ggml-alloc.h'. +// +// ********************************************************************* + +/** + * GGML_API struct ggml_tallocr ggml_tallocr_new(ggml_backend_buffer_t buffer); + */ +class GGML_tallocr_new extends MustUse { + GGML_tallocr_new() { + this.getName() = "ggml_tallocr_new" + } +} + +/** + * GGML_API void ggml_tallocr_alloc( + * struct ggml_tallocr * talloc, + * struct ggml_tensor * tensor + * ); + */ +class GGML_tallocr_alloc extends Function { + GGML_tallocr_alloc() { + this.getName() = "ggml_tallocr_alloc" + } +} /** * GGML_API ggml_gallocr_t ggml_gallocr_new(ggml_backend_buffer_type_t buft); - * - * The allocator guarantees that the return value and internal fields are not NULL. */ class GGML_gallocr_new extends Alloc { - GGML_gallocr_new() { this.getName() = "ggml_gallocr_new" } + GGML_gallocr_new() { + this.getName() = "ggml_gallocr_new" + } } /** - * GGML_API ggml_gallocr_t ggml_gallocr_new_n(ggml_backend_buffer_type_t * bufts, int n_bufs); + * GGML_API ggml_gallocr_t ggml_gallocr_new_n( + * ggml_backend_buffer_type_t * bufts, + * int n_bufs + * ); */ -class GGML_gallocr_new_n extends Alloc { - GGML_gallocr_new_n() { this.getName() = "ggml_gallocr_new_n" } +class GGML_gallocr_new_n extends Alloc { + GGML_gallocr_new_n() { + this.getName() = "ggml_gallocr_new_n" + } } /** * GGML_API void ggml_gallocr_free(ggml_gallocr_t galloc); */ class GGML_gallocr_free extends Free { - GGML_gallocr_free() { this.getName() = "ggml_gallocr_free" } + GGML_gallocr_free() { + this.getName() = "ggml_gallocr_free" + } } /** - * GGML_API bool ggml_gallocr_alloc_graph(ggml_gallocr_t galloc, struct ggml_cgraph * graph); + * GGML_API bool ggml_gallocr_reserve( + * ggml_gallocr_t galloc, + * struct ggml_cgraph * graph + * ); */ -class GGML_gallocr_alloc_graph extends MustCheck { - GGML_gallocr_alloc_graph() { this.getName() = "ggml_gallocr_alloc_graph" } - - override string getMessage() { - result = "The return value of `" + this.getName() + "` should be checked to ensure that the buffer allocation succeeded" +class GGML_gallocr_reserve extends MustUse { + GGML_gallocr_reserve() { + this.getName() = "ggml_gallocr_reserve" } } /** - * GGML_API bool ggml_gallocr_reserve(ggml_gallocr_t galloc, struct ggml_cgraph * graph); + * GGML_API bool ggml_gallocr_reserve_n( + * ggml_gallocr_t galloc, + * struct ggml_cgraph * graph, + * const int * node_buffer_ids, + * const int * leaf_buffer_ids + * ); */ -class GGML_gallocr_reserve extends MustCheck { - GGML_gallocr_reserve() { this.getName() = "ggml_gallocr_reserve" } - - override string getMessage() { - result = "The return value of `" + this.getName() + "` should be checked to ensure that the buffer allocation succeeded" +class GGML_gallocr_reserve_n extends MustUse { + GGML_gallocr_reserve_n() { + this.getName() = "ggml_gallocr_reserve_n" } -} +} /** - * GGML_API bool ggml_gallocr_reserve_n( + * GGML_API bool ggml_gallocr_alloc_graph( * ggml_gallocr_t galloc, - * struct ggml_cgraph * graph, - * const int * node_buffer_ids, - * const int * leaf_buffer_ids); + * struct ggml_cgraph * graph + * ); */ -class GGML_gallocr_reserve_n extends MustCheck { - GGML_gallocr_reserve_n() { this.getName() = "ggml_gallocr_reserve_n" } - - override string getMessage() { - result = "The return value of `" + this.getName() + "` should be checked to ensure that the buffer allocation succeeded" +class GGML_gallocr_alloc_graph extends MustUse { + GGML_gallocr_alloc_graph() { + this.getName() = "ggml_gallocr_alloc_graph" } } /** - * GGML_API size_t ggml_gallocr_get_buffer_size(ggml_gallocr_t galloc, int buffer_id); + * GGML_API size_t ggml_gallocr_get_buffer_size( + * ggml_gallocr_t galloc, + * int buffer_id + * ); */ class GGML_gallocr_get_buffer_size extends MustUse { - GGML_gallocr_get_buffer_size() { this.getName() = "ggml_gallocr_get_buffer_size" } + GGML_gallocr_get_buffer_size() { + this.getName() = "ggml_gallocr_get_buffer_size" + } } -class GraphAllocator extends CustomAllocator { - GraphAllocator() { this = "GraphAllocator" } - +// ********************************************************************* +// +// Custom allocators defined by 'ggml-alloc.h'. +// +// ********************************************************************* + +/** + * Alloc: + * ggml_gallocr_new + * + * Free: + * ggml_gallocr_new + */ +class GGMLGraphAllocator extends CustomAllocator { + GGMLGraphAllocator() { this = "GGMLGraphAllocator" } + override predicate isAlloc(Alloc f) { (f instanceof GGML_gallocr_new) or (f instanceof GGML_gallocr_new_n) } @@ -77,4 +138,4 @@ class GraphAllocator extends CustomAllocator { override predicate isFree(Free f) { f instanceof GGML_gallocr_free } -} \ No newline at end of file +} diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll index 1b9f7a8..2112fea 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll @@ -1,98 +1,443 @@ +// ********************************************************************* +// +// This library has been automatically generated using the Busy Work +// VSCode extension from the file 'ggml-backend.h'. +// +// ********************************************************************* import cpp -import trailofbits.ml.common +import trailofbits.common + +// ********************************************************************* +// +// Function types matching the individual functions defined by +// 'ggml-backend.h'. +// +// ********************************************************************* /** - * GGML_API ggml_backend_buffer_t ggml_backend_buft_alloc_buffer( - * ggml_backend_buffer_type_t buft, + * GGML_API GGML_CALL ggml_backend_buffer_t ggml_backend_buft_alloc_buffer ( + * ggml_backend_buffer_type_t buft, * size_t size * ); */ -class GGML_backend_buft_alloc_buffer extends Alloc { +class GGML_backend_buft_alloc_buffer extends MustUse { GGML_backend_buft_alloc_buffer() { this.getName() = "ggml_backend_buft_alloc_buffer" } } /** - * GGML_API void ggml_backend_buffer_free(ggml_backend_buffer_t buffer); + * GGML_API size_t ggml_backend_buft_get_alignment ( + * ggml_backend_buffer_type_t buft + * ); + */ +class GGML_backend_buft_get_alignment extends MustUse { + GGML_backend_buft_get_alignment() { + this.getName() = "ggml_backend_buft_get_alignment" + } +} + +/** + * GGML_API size_t ggml_backend_buft_get_max_size ( + * ggml_backend_buffer_type_t buft + * ); + */ +class GGML_backend_buft_get_max_size extends MustUse { + GGML_backend_buft_get_max_size() { + this.getName() = "ggml_backend_buft_get_max_size" + } +} + +/** + * GGML_API GGML_CALL size_t ggml_backend_buft_get_alloc_size ( + * ggml_backend_buffer_type_t buft, + * struct ggml_tensor * tensor + * ); + */ +class GGML_backend_buft_get_alloc_size extends MustUse { + GGML_backend_buft_get_alloc_size() { + this.getName() = "ggml_backend_buft_get_alloc_size" + } +} + +/** + * GGML_API bool ggml_backend_buft_supports_backend( + * ggml_backend_buffer_type_t buft, + * ggml_backend_t backend + * ); + */ +class GGML_backend_buft_supports_backend extends MustUse { + GGML_backend_buft_supports_backend() { + this.getName() = "ggml_backend_buft_supports_backend" + } +} + +/** + * GGML_API bool ggml_backend_buft_is_host (ggml_backend_buffer_type_t buft); + */ +class GGML_backend_buft_is_host extends MustUse { + GGML_backend_buft_is_host() { + this.getName() = "ggml_backend_buft_is_host" + } +} + +/** + * GGML_API void ggml_backend_buffer_free (ggml_backend_buffer_t buffer); */ -class GGML_backend_buffer_free extends Free { +class GGML_backend_buffer_free extends Function { GGML_backend_buffer_free() { this.getName() = "ggml_backend_buffer_free" } } /** - * GGML_API ggml_backend_sched_t ggml_backend_sched_new( - * ggml_backend_t * backends, - * ggml_backend_buffer_type_t * bufts, - * int n_backends, - * size_t graph_size, - * bool parallel + * GGML_API size_t ggml_backend_buffer_get_size (ggml_backend_buffer_t buffer); + */ +class GGML_backend_buffer_get_size extends MustUse { + GGML_backend_buffer_get_size() { + this.getName() = "ggml_backend_buffer_get_size" + } +} + +/** + * GGML_API GGML_CALL void ggml_backend_buffer_init_tensor ( + * ggml_backend_buffer_t buffer, + * struct ggml_tensor * tensor * ); */ -class GGML_backend_sched_new extends Alloc { - GGML_backend_sched_new() { - this.getName() = "ggml_backend_sched_new" +class GGML_backend_buffer_init_tensor extends Function { + GGML_backend_buffer_init_tensor() { + this.getName() = "ggml_backend_buffer_init_tensor" } } /** - * GGML_API void ggml_backend_sched_free(ggml_backend_sched_t sched); + * GGML_API size_t ggml_backend_buffer_get_alignment ( + * ggml_backend_buffer_t buffer + * ); */ -class GGML_backend_sched_free extends Free { - GGML_backend_sched_free() { - this.getName() = "ggml_backend_sched_free" +class GGML_backend_buffer_get_alignment extends MustUse { + GGML_backend_buffer_get_alignment() { + this.getName() = "ggml_backend_buffer_get_alignment" } } /** - * GGML_API struct ggml_backend_graph_copy ggml_backend_graph_copy( - * ggml_backend_t backend, - * struct ggml_cgraph * graph + * GGML_API size_t ggml_backend_buffer_get_max_size ( + * ggml_backend_buffer_t buffer * ); */ -class GGML_backend_graph_copy extends Alloc { - GGML_backend_graph_copy() { - this.getName() = "ggml_backend_graph_copy" +class GGML_backend_buffer_get_max_size extends MustUse { + GGML_backend_buffer_get_max_size() { + this.getName() = "ggml_backend_buffer_get_max_size" } } /** - * GGML_API void ggml_backend_graph_copy_free(struct ggml_backend_graph_copy copy); + * GGML_API size_t ggml_backend_buffer_get_alloc_size( + * ggml_backend_buffer_t buffer, + * struct ggml_tensor * tensor + * ); */ -class GGML_backend_graph_copy_free extends Free { - GGML_backend_graph_copy_free() { - this.getName() = "ggml_backend_graph_copy_free" +class GGML_backend_buffer_get_alloc_size extends MustUse { + GGML_backend_buffer_get_alloc_size() { + this.getName() = "ggml_backend_buffer_get_alloc_size" + } +} + +/** + * GGML_API void ggml_backend_buffer_clear ( + * ggml_backend_buffer_t buffer, + * uint8_t value + * ); + */ +class GGML_backend_buffer_clear extends Function { + GGML_backend_buffer_clear() { + this.getName() = "ggml_backend_buffer_clear" + } +} + +/** + * GGML_API bool ggml_backend_buffer_is_host (ggml_backend_buffer_t buffer); + */ +class GGML_backend_buffer_is_host extends MustUse { + GGML_backend_buffer_is_host() { + this.getName() = "ggml_backend_buffer_is_host" + } +} + +/** + * GGML_API void ggml_backend_buffer_set_usage ( + * ggml_backend_buffer_t buffer, + * enum ggml_backend_buffer_usage usage + * ); + */ +class GGML_backend_buffer_set_usage extends Function { + GGML_backend_buffer_set_usage() { + this.getName() = "ggml_backend_buffer_set_usage" + } +} + +/** + * GGML_API ggml_backend_buffer_type_t ggml_backend_buffer_get_type ( + * ggml_backend_buffer_t buffer + * ); + */ +class GGML_backend_buffer_get_type extends MustUse { + GGML_backend_buffer_get_type() { + this.getName() = "ggml_backend_buffer_get_type" + } +} + +/** + * GGML_API void ggml_backend_buffer_reset (ggml_backend_buffer_t buffer); + */ +class GGML_backend_buffer_reset extends Function { + GGML_backend_buffer_reset() { + this.getName() = "ggml_backend_buffer_reset" + } +} + +/** + * GGML_API ggml_guid_t ggml_backend_guid(ggml_backend_t backend); + */ +class GGML_backend_guid extends MustUse { + GGML_backend_guid() { + this.getName() = "ggml_backend_guid" + } +} + +/** + * GGML_API void ggml_backend_free(ggml_backend_t backend); + */ +class GGML_backend_free extends Function { + GGML_backend_free() { + this.getName() = "ggml_backend_free" + } +} + +/** + * GGML_API ggml_backend_buffer_type_t ggml_backend_get_default_buffer_type( + * ggml_backend_t backend + * ); + */ +class GGML_backend_get_default_buffer_type extends MustUse { + GGML_backend_get_default_buffer_type() { + this.getName() = "ggml_backend_get_default_buffer_type" + } +} + +/** + * GGML_API ggml_backend_buffer_t ggml_backend_alloc_buffer( + * ggml_backend_t backend, + * size_t size + * ); + */ +class GGML_backend_alloc_buffer extends MustUse { + GGML_backend_alloc_buffer() { + this.getName() = "ggml_backend_alloc_buffer" + } +} + +/** + * GGML_API size_t ggml_backend_get_alignment(ggml_backend_t backend); + */ +class GGML_backend_get_alignment extends MustUse { + GGML_backend_get_alignment() { + this.getName() = "ggml_backend_get_alignment" + } +} + +/** + * GGML_API size_t ggml_backend_get_max_size(ggml_backend_t backend); + */ +class GGML_backend_get_max_size extends MustUse { + GGML_backend_get_max_size() { + this.getName() = "ggml_backend_get_max_size" + } +} + +/** + * GGML_API void ggml_backend_tensor_set_async( + * ggml_backend_t backend, + * struct ggml_tensor * tensor, + * const void * data, + * size_t offset, + * size_t size + * ); + */ +class GGML_backend_tensor_set_async extends Function { + GGML_backend_tensor_set_async() { + this.getName() = "ggml_backend_tensor_set_async" + } +} + +/** + * GGML_API void ggml_backend_tensor_get_async( + * ggml_backend_t backend, + * const struct ggml_tensor * tensor, + * void * data, + * size_t offset, + * size_t size + * ); + */ +class GGML_backend_tensor_get_async extends Function { + GGML_backend_tensor_get_async() { + this.getName() = "ggml_backend_tensor_get_async" + } +} + +/** + * GGML_API GGML_CALL void ggml_backend_tensor_set( + * struct ggml_tensor * tensor, + * const void * data, + * size_t offset, + * size_t size + * ); + */ +class GGML_backend_tensor_set extends Function { + GGML_backend_tensor_set() { + this.getName() = "ggml_backend_tensor_set" + } +} + +/** + * GGML_API GGML_CALL void ggml_backend_tensor_get( + * const struct ggml_tensor * tensor, + * void * data, + * size_t offset, + * size_t size + * ); + */ +class GGML_backend_tensor_get extends Function { + GGML_backend_tensor_get() { + this.getName() = "ggml_backend_tensor_get" + } +} + +/** + * GGML_API void ggml_backend_synchronize(ggml_backend_t backend); + */ +class GGML_backend_synchronize extends Function { + GGML_backend_synchronize() { + this.getName() = "ggml_backend_synchronize" } } /** * GGML_API ggml_backend_graph_plan_t ggml_backend_graph_plan_create( - * ggml_backend_t backend, - * struct ggml_cgraph *cgraph + * ggml_backend_t backend, + * struct ggml_cgraph * cgraph * ); */ -class GGML_backend_graph_plan_create extends Alloc { +class GGML_backend_graph_plan_create extends MustUse { GGML_backend_graph_plan_create() { this.getName() = "ggml_backend_graph_plan_create" } } /** - * GGML_API void ggml_backend_graph_plan_free( - * ggml_backend_t backend, + * GGML_API void ggml_backend_graph_plan_free ( + * ggml_backend_t backend, * ggml_backend_graph_plan_t plan * ); */ -class GGML_backend_graph_plan_free extends Free { +class GGML_backend_graph_plan_free extends Function { GGML_backend_graph_plan_free() { this.getName() = "ggml_backend_graph_plan_free" } } /** - * GGML_API ggml_backend_event_t ggml_backend_event_new(ggml_backend_t backend); + * GGML_API enum ggml_status ggml_backend_graph_plan_compute ( + * ggml_backend_t backend, + * ggml_backend_graph_plan_t plan + * ); + */ +class GGML_backend_graph_plan_compute extends MustUse { + GGML_backend_graph_plan_compute() { + this.getName() = "ggml_backend_graph_plan_compute" + } +} + +/** + * GGML_API enum ggml_status ggml_backend_graph_compute ( + * ggml_backend_t backend, + * struct ggml_cgraph * cgraph + * ); + */ +class GGML_backend_graph_compute extends MustUse { + GGML_backend_graph_compute() { + this.getName() = "ggml_backend_graph_compute" + } +} + +/** + * GGML_API enum ggml_status ggml_backend_graph_compute_async( + * ggml_backend_t backend, + * struct ggml_cgraph * cgraph + * ); + */ +class GGML_backend_graph_compute_async extends MustUse { + GGML_backend_graph_compute_async() { + this.getName() = "ggml_backend_graph_compute_async" + } +} + +/** + * GGML_API bool ggml_backend_supports_op( + * ggml_backend_t backend, + * const struct ggml_tensor * op + * ); + */ +class GGML_backend_supports_op extends MustUse { + GGML_backend_supports_op() { + this.getName() = "ggml_backend_supports_op" + } +} + +/** + * GGML_API bool ggml_backend_offload_op( + * ggml_backend_t backend, + * const struct ggml_tensor * op + * ); + */ +class GGML_backend_offload_op extends MustUse { + GGML_backend_offload_op() { + this.getName() = "ggml_backend_offload_op" + } +} + +/** + * GGML_API void ggml_backend_tensor_copy( + * struct ggml_tensor * src, + * struct ggml_tensor * dst + * ); + */ +class GGML_backend_tensor_copy extends Function { + GGML_backend_tensor_copy() { + this.getName() = "ggml_backend_tensor_copy" + } +} + +/** + * GGML_API void ggml_backend_tensor_copy_async( + * ggml_backend_t backend_src, + * ggml_backend_t backend_dst, + * struct ggml_tensor * src, + * struct ggml_tensor * dst + * ); + */ +class GGML_backend_tensor_copy_async extends Function { + GGML_backend_tensor_copy_async() { + this.getName() = "ggml_backend_tensor_copy_async" + } +} + +/** + * GGML_API ggml_backend_event_t ggml_backend_event_new ( + * ggml_backend_t backend + * ); */ class GGML_backend_event_new extends Alloc { GGML_backend_event_new() { @@ -101,7 +446,7 @@ class GGML_backend_event_new extends Alloc { } /** - * GGML_API void ggml_backend_event_free(ggml_backend_event_t event); + * GGML_API void ggml_backend_event_free (ggml_backend_event_t event); */ class GGML_backend_event_free extends Free { GGML_backend_event_free() { @@ -109,62 +454,436 @@ class GGML_backend_event_free extends Free { } } -class BackendBufferAllocator extends CustomAllocator { - BackendBufferAllocator() { this = "BackendBufferAllocator" } - - override predicate isAlloc(Alloc f) { - f instanceof GGML_backend_buft_alloc_buffer +/** + * GGML_API void ggml_backend_event_record (ggml_backend_event_t event); + */ +class GGML_backend_event_record extends Function { + GGML_backend_event_record() { + this.getName() = "ggml_backend_event_record" } +} - override predicate isFree(Free f) { - f instanceof GGML_backend_buffer_free +/** + * GGML_API void ggml_backend_event_synchronize(ggml_backend_event_t event); + */ +class GGML_backend_event_synchronize extends Function { + GGML_backend_event_synchronize() { + this.getName() = "ggml_backend_event_synchronize" } } -class BackendSchedulerAllocator extends CustomAllocator { - BackendSchedulerAllocator() { this = "BackendSchedulerAllocator" } - - override predicate isAlloc(Alloc f) { - f instanceof GGML_backend_sched_new +/** + * GGML_API void ggml_backend_event_wait ( + * ggml_backend_t backend, + * ggml_backend_event_t event + * ); + */ +class GGML_backend_event_wait extends Function { + GGML_backend_event_wait() { + this.getName() = "ggml_backend_event_wait" } +} - override predicate isFree(Free f) { - f instanceof GGML_backend_sched_free +/** + * GGML_API ggml_backend_t ggml_backend_cpu_init(void); + */ +class GGML_backend_cpu_init extends MustUse { + GGML_backend_cpu_init() { + this.getName() = "ggml_backend_cpu_init" } } -class BackendGraphCopyAllocator extends CustomAllocator { - BackendGraphCopyAllocator() { this = "BackendGraphCopyAllocator" } - - override predicate isAlloc(Alloc f) { - f instanceof GGML_backend_graph_copy +/** + * GGML_API GGML_CALL bool ggml_backend_is_cpu (ggml_backend_t backend); + */ +class GGML_backend_is_cpu extends MustUse { + GGML_backend_is_cpu() { + this.getName() = "ggml_backend_is_cpu" } +} - override predicate isFree(Free f) { - f instanceof GGML_backend_graph_copy_free +/** + * GGML_API void ggml_backend_cpu_set_n_threads ( + * ggml_backend_t backend_cpu, + * int n_threads + * ); + */ +class GGML_backend_cpu_set_n_threads extends Function { + GGML_backend_cpu_set_n_threads() { + this.getName() = "ggml_backend_cpu_set_n_threads" } } -class BackendGraphPlanAllocator extends CustomAllocator { - BackendGraphPlanAllocator() { this = "BackendGraphPlanAllocator" } - - override predicate isAlloc(Alloc f) { - f instanceof GGML_backend_graph_plan_create +/** + * GGML_API void ggml_backend_cpu_set_abort_callback( + * ggml_backend_t backend_cpu, + * ggml_abort_callback abort_callback, + * void * abort_callback_data + * ); + */ +class GGML_backend_cpu_set_abort_callback extends Function { + GGML_backend_cpu_set_abort_callback() { + this.getName() = "ggml_backend_cpu_set_abort_callback" } +} - override predicate isFree(Free f) { - f instanceof GGML_backend_graph_plan_free +/** + * GGML_API GGML_CALL ggml_backend_buffer_t ggml_backend_cpu_buffer_from_ptr( + * void * ptr, + * size_t size + * ); + */ +class GGML_backend_cpu_buffer_from_ptr extends MustUse { + GGML_backend_cpu_buffer_from_ptr() { + this.getName() = "ggml_backend_cpu_buffer_from_ptr" + } +} + +/** + * GGML_API GGML_CALL ggml_backend_buffer_type_t ggml_backend_cpu_buffer_type( + * void + * ); + */ +class GGML_backend_cpu_buffer_type extends MustUse { + GGML_backend_cpu_buffer_type() { + this.getName() = "ggml_backend_cpu_buffer_type" + } +} + +/** + * GGML_API ggml_backend_buffer_type_t ggml_backend_cpu_hbm_buffer_type(void); + */ +class GGML_backend_cpu_hbm_buffer_type extends MustUse { + GGML_backend_cpu_hbm_buffer_type() { + this.getName() = "ggml_backend_cpu_hbm_buffer_type" + } +} + +/** + * GGML_API size_t ggml_backend_reg_get_count(void); + */ +class GGML_backend_reg_get_count extends MustUse { + GGML_backend_reg_get_count() { + this.getName() = "ggml_backend_reg_get_count" + } +} + +/** + * GGML_API size_t ggml_backend_reg_find_by_name(const char * name); + */ +class GGML_backend_reg_find_by_name extends MustUse { + GGML_backend_reg_find_by_name() { + this.getName() = "ggml_backend_reg_find_by_name" + } +} + +/** + * GGML_API ggml_backend_t ggml_backend_reg_init_backend_from_str( + * const char * backend_str + * ); + */ +class GGML_backend_reg_init_backend_from_str extends MustUse { + GGML_backend_reg_init_backend_from_str() { + this.getName() = "ggml_backend_reg_init_backend_from_str" + } +} + +/** + * GGML_API ggml_backend_t ggml_backend_reg_init_backend( + * size_t i, + * const char * params + * ); + */ +class GGML_backend_reg_init_backend extends MustUse { + GGML_backend_reg_init_backend() { + this.getName() = "ggml_backend_reg_init_backend" + } +} + +/** + * GGML_API ggml_backend_buffer_type_t ggml_backend_reg_get_default_buffer_type( + * size_t i + * ); + */ +class GGML_backend_reg_get_default_buffer_type extends MustUse { + GGML_backend_reg_get_default_buffer_type() { + this.getName() = "ggml_backend_reg_get_default_buffer_type" + } +} + +/** + * GGML_API ggml_backend_buffer_t ggml_backend_reg_alloc_buffer( + * size_t i, + * size_t size + * ); + */ +class GGML_backend_reg_alloc_buffer extends MustUse { + GGML_backend_reg_alloc_buffer() { + this.getName() = "ggml_backend_reg_alloc_buffer" + } +} + +/** + * GGML_API ggml_backend_sched_t ggml_backend_sched_new( + * ggml_backend_t * backends, + * ggml_backend_buffer_type_t * bufts, + * int n_backends, + * size_t graph_size, + * bool parallel + * ); + */ +class GGML_backend_sched_new extends Alloc { + GGML_backend_sched_new() { + this.getName() = "ggml_backend_sched_new" + } +} + +/** + * GGML_API void ggml_backend_sched_free(ggml_backend_sched_t sched); + */ +class GGML_backend_sched_free extends Free { + GGML_backend_sched_free() { + this.getName() = "ggml_backend_sched_free" + } +} + +/** + * GGML_API bool ggml_backend_sched_reserve( + * ggml_backend_sched_t sched, + * struct ggml_cgraph * measure_graph + * ); + */ +class GGML_backend_sched_reserve extends MustUse { + GGML_backend_sched_reserve() { + this.getName() = "ggml_backend_sched_reserve" + } +} + +/** + * GGML_API int ggml_backend_sched_get_n_splits(ggml_backend_sched_t sched); + */ +class GGML_backend_sched_get_n_splits extends MustUse { + GGML_backend_sched_get_n_splits() { + this.getName() = "ggml_backend_sched_get_n_splits" + } +} + +/** + * GGML_API int ggml_backend_sched_get_n_copies(ggml_backend_sched_t sched); + */ +class GGML_backend_sched_get_n_copies extends MustUse { + GGML_backend_sched_get_n_copies() { + this.getName() = "ggml_backend_sched_get_n_copies" + } +} + +/** + * GGML_API size_t ggml_backend_sched_get_buffer_size( + * ggml_backend_sched_t sched, + * ggml_backend_t backend + * ); + */ +class GGML_backend_sched_get_buffer_size extends MustUse { + GGML_backend_sched_get_buffer_size() { + this.getName() = "ggml_backend_sched_get_buffer_size" + } +} + +/** + * GGML_API void ggml_backend_sched_set_tensor_backend( + * ggml_backend_sched_t sched, + * struct ggml_tensor * node, + * ggml_backend_t backend + * ); + */ +class GGML_backend_sched_set_tensor_backend extends Function { + GGML_backend_sched_set_tensor_backend() { + this.getName() = "ggml_backend_sched_set_tensor_backend" + } +} + +/** + * GGML_API ggml_backend_t ggml_backend_sched_get_tensor_backend( + * ggml_backend_sched_t sched, + * struct ggml_tensor * node + * ); + */ +class GGML_backend_sched_get_tensor_backend extends MustUse { + GGML_backend_sched_get_tensor_backend() { + this.getName() = "ggml_backend_sched_get_tensor_backend" + } +} + +/** + * GGML_API bool ggml_backend_sched_alloc_graph( + * ggml_backend_sched_t sched, + * struct ggml_cgraph * graph + * ); + */ +class GGML_backend_sched_alloc_graph extends MustUse { + GGML_backend_sched_alloc_graph() { + this.getName() = "ggml_backend_sched_alloc_graph" + } +} + +/** + * GGML_API enum ggml_status ggml_backend_sched_graph_compute( + * ggml_backend_sched_t sched, + * struct ggml_cgraph * graph + * ); + */ +class GGML_backend_sched_graph_compute extends MustUse { + GGML_backend_sched_graph_compute() { + this.getName() = "ggml_backend_sched_graph_compute" + } +} + +/** + * GGML_API enum ggml_status ggml_backend_sched_graph_compute_async( + * ggml_backend_sched_t sched, + * struct ggml_cgraph * graph + * ); + */ +class GGML_backend_sched_graph_compute_async extends MustUse { + GGML_backend_sched_graph_compute_async() { + this.getName() = "ggml_backend_sched_graph_compute_async" + } +} + +/** + * GGML_API void ggml_backend_sched_synchronize(ggml_backend_sched_t sched); + */ +class GGML_backend_sched_synchronize extends Function { + GGML_backend_sched_synchronize() { + this.getName() = "ggml_backend_sched_synchronize" + } +} + +/** + * GGML_API void ggml_backend_sched_reset(ggml_backend_sched_t sched); + */ +class GGML_backend_sched_reset extends Function { + GGML_backend_sched_reset() { + this.getName() = "ggml_backend_sched_reset" + } +} + +/** + * GGML_API void ggml_backend_sched_set_eval_callback( + * ggml_backend_sched_t sched, + * ggml_backend_sched_eval_callback callback, + * void * user_data + * ); + */ +class GGML_backend_sched_set_eval_callback extends Function { + GGML_backend_sched_set_eval_callback() { + this.getName() = "ggml_backend_sched_set_eval_callback" + } +} + +/** + * GGML_API struct ggml_backend_graph_copy ggml_backend_graph_copy( + * ggml_backend_t backend, + * struct ggml_cgraph * graph + * ); + */ +class GGML_backend_graph_copy extends MustUse { + GGML_backend_graph_copy() { + this.getName() = "ggml_backend_graph_copy" + } +} + +/** + * GGML_API void ggml_backend_graph_copy_free( + * struct ggml_backend_graph_copy copy + * ); + */ +class GGML_backend_graph_copy_free extends Function { + GGML_backend_graph_copy_free() { + this.getName() = "ggml_backend_graph_copy_free" + } +} + +/** + * GGML_API bool ggml_backend_compare_graph_backend( + * ggml_backend_t backend1, + * ggml_backend_t backend2, + * struct ggml_cgraph * graph, + * ggml_backend_eval_callback callback, + * void * user_data + * ); + */ +class GGML_backend_compare_graph_backend extends MustUse { + GGML_backend_compare_graph_backend() { + this.getName() = "ggml_backend_compare_graph_backend" + } +} + +/** + * GGML_API void ggml_backend_tensor_alloc( + * ggml_backend_buffer_t buffer, + * struct ggml_tensor * tensor, + * void * addr + * ); + */ +class GGML_backend_tensor_alloc extends Function { + GGML_backend_tensor_alloc() { + this.getName() = "ggml_backend_tensor_alloc" } } -class BackendEventAllocator extends CustomAllocator { - BackendEventAllocator() { this = "BackendEventAllocator" } - +/** + * GGML_API void ggml_backend_view_init( + * ggml_backend_buffer_t buffer, + * struct ggml_tensor * tensor + * ); + */ +class GGML_backend_view_init extends Function { + GGML_backend_view_init() { + this.getName() = "ggml_backend_view_init" + } +} + +// ********************************************************************* +// +// Custom allocators defined by 'ggml-backend.h'. +// +// ********************************************************************* + +/** + * Alloc: + * ggml_backend_event_new + * + * Free: + * ggml_backend_event_free + */ +class GGMLBackendEventAllocator extends CustomAllocator { + GGMLBackendEventAllocator() { this = "GGMLBackendEventAllocator" } + override predicate isAlloc(Alloc f) { f instanceof GGML_backend_event_new } override predicate isFree(Free f) { f instanceof GGML_backend_event_free - } -} \ No newline at end of file + } +} + +/** + * Alloc: + * ggml_backend_sched_new + * + * Free: + * ggml_backend_sched_free + */ +class GGMLBackendScheduleAllocator extends CustomAllocator { + GGMLBackendScheduleAllocator() { this = "GGMLBackendScheduleAllocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_sched_new + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_sched_free + } +} From 4a36e9e36b2d93284b6b533be12132c7ef20e179 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Thu, 27 Jun 2024 12:51:07 +0200 Subject: [PATCH 16/19] Updated auto-generated QL libraries for GGML header files --- cpp/lib/trailofbits/ml/ggml/ggml.qll | 3066 ++++++++++++++++-- cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll | 51 +- cpp/lib/trailofbits/ml/ggml/ggml_backend.qll | 89 +- 3 files changed, 2969 insertions(+), 237 deletions(-) diff --git a/cpp/lib/trailofbits/ml/ggml/ggml.qll b/cpp/lib/trailofbits/ml/ggml/ggml.qll index 10b26fb..1e88d47 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml.qll @@ -1,7 +1,7 @@ // ********************************************************************* // -// This library has been automatically generated using the Busy Work -// VSCode extension from the file 'ggml.h'. +// This library has been automatically generated using the QLL Writer +// VSCode extension from the the file ggml.h // // ********************************************************************* import cpp @@ -9,11 +9,22 @@ import trailofbits.common // ********************************************************************* // -// Function types matching the individual functions defined by -// 'ggml.h'. +// Function types matching the individual functions defined in +// ggml.h // // ********************************************************************* +/** + * GGML_API GGML_CALL const char * ggml_status_to_string( + * enum ggml_status status + * ); + */ +class GGML_status_to_string extends MustCheck { + GGML_status_to_string() { + this.getName() = "ggml_status_to_string" + } +} + /** * GGML_API float ggml_fp16_to_fp32(ggml_fp16_t x); */ @@ -121,6 +132,15 @@ class GGML_print_backtrace extends Function { } } +/** + * GGML_API FILE * ggml_fopen(const char * fname, const char * mode); + */ +class GGML_fopen extends MustCheck { + GGML_fopen() { + this.getName() = "ggml_fopen" + } +} + /** * GGML_API void ggml_numa_init(enum ggml_numa_strategy numa); */ @@ -222,6 +242,51 @@ class GGML_row_size extends MustUse { } } +/** + * GGML_API GGML_CALL const char * ggml_type_name(enum ggml_type type); + */ +class GGML_type_name extends MustCheck { + GGML_type_name() { + this.getName() = "ggml_type_name" + } +} + +/** + * GGML_API GGML_CALL const char * ggml_op_name (enum ggml_op op); + */ +class GGML_op_name extends MustCheck { + GGML_op_name() { + this.getName() = "ggml_op_name" + } +} + +/** + * GGML_API const char * ggml_op_symbol(enum ggml_op op); + */ +class GGML_op_symbol extends MustCheck { + GGML_op_symbol() { + this.getName() = "ggml_op_symbol" + } +} + +/** + * GGML_API const char * ggml_unary_op_name(enum ggml_unary_op op); + */ +class GGML_unary_op_name extends MustCheck { + GGML_unary_op_name() { + this.getName() = "ggml_unary_op_name" + } +} + +/** + * GGML_API GGML_CALL const char * ggml_op_desc(const struct ggml_tensor * t); + */ +class GGML_op_desc extends MustCheck { + GGML_op_desc() { + this.getName() = "ggml_op_desc" + } +} + /** * GGML_API GGML_CALL size_t ggml_element_size( * const struct ggml_tensor * tensor @@ -301,295 +366,2832 @@ class GGML_is_scalar extends MustUse { } /** - * GGML_API bool ggml_is_vector (const struct ggml_tensor * tensor); + * GGML_API bool ggml_is_vector (const struct ggml_tensor * tensor); + */ +class GGML_is_vector extends MustUse { + GGML_is_vector() { + this.getName() = "ggml_is_vector" + } +} + +/** + * GGML_API bool ggml_is_matrix (const struct ggml_tensor * tensor); + */ +class GGML_is_matrix extends MustUse { + GGML_is_matrix() { + this.getName() = "ggml_is_matrix" + } +} + +/** + * GGML_API bool ggml_is_3d (const struct ggml_tensor * tensor); + */ +class GGML_is_3d extends MustUse { + GGML_is_3d() { + this.getName() = "ggml_is_3d" + } +} + +/** + * GGML_API int ggml_n_dims (const struct ggml_tensor * tensor); + */ +class GGML_n_dims extends MustUse { + GGML_n_dims() { + this.getName() = "ggml_n_dims" + } +} + +/** + * GGML_API bool ggml_are_same_shape( + * const struct ggml_tensor * t0, + * const struct ggml_tensor * t1 + * ); + */ +class GGML_are_same_shape extends MustUse { + GGML_are_same_shape() { + this.getName() = "ggml_are_same_shape" + } +} + +/** + * GGML_API size_t ggml_tensor_overhead(void); + */ +class GGML_tensor_overhead extends MustUse { + GGML_tensor_overhead() { + this.getName() = "ggml_tensor_overhead" + } +} + +/** + * GGML_API struct ggml_context * ggml_init(struct ggml_init_params params); + */ +class GGML_init extends MustCheck { + GGML_init() { + this.getName() = "ggml_init" + } +} + +/** + * GGML_API void ggml_free(struct ggml_context * ctx); + */ +class GGML_free extends Function { + GGML_free() { + this.getName() = "ggml_free" + } +} + +/** + * GGML_API size_t ggml_used_mem(const struct ggml_context * ctx); + */ +class GGML_used_mem extends MustUse { + GGML_used_mem() { + this.getName() = "ggml_used_mem" + } +} + +/** + * GGML_API size_t ggml_set_scratch ( + * struct ggml_context * ctx, + * struct ggml_scratch scratch + * ); + */ +class GGML_set_scratch extends MustUse { + GGML_set_scratch() { + this.getName() = "ggml_set_scratch" + } +} + +/** + * GGML_API bool ggml_get_no_alloc(struct ggml_context * ctx); + */ +class GGML_get_no_alloc extends MustUse { + GGML_get_no_alloc() { + this.getName() = "ggml_get_no_alloc" + } +} + +/** + * GGML_API void ggml_set_no_alloc(struct ggml_context * ctx, bool no_alloc); + */ +class GGML_set_no_alloc extends Function { + GGML_set_no_alloc() { + this.getName() = "ggml_set_no_alloc" + } +} + +/** + * GGML_API void * ggml_get_mem_buffer (const struct ggml_context * ctx); + */ +class GGML_get_mem_buffer extends MustCheck { + GGML_get_mem_buffer() { + this.getName() = "ggml_get_mem_buffer" + } +} + +/** + * GGML_API size_t ggml_get_mem_size (const struct ggml_context * ctx); + */ +class GGML_get_mem_size extends MustUse { + GGML_get_mem_size() { + this.getName() = "ggml_get_mem_size" + } +} + +/** + * GGML_API size_t ggml_get_max_tensor_size(const struct ggml_context * ctx); + */ +class GGML_get_max_tensor_size extends MustUse { + GGML_get_max_tensor_size() { + this.getName() = "ggml_get_max_tensor_size" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_tensor( + * struct ggml_context * ctx, + * enum ggml_type type, + * int n_dims, + * const int64_t *ne + * ); + */ +class GGML_new_tensor extends MustCheck { + GGML_new_tensor() { + this.getName() = "ggml_new_tensor" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_tensor_1d( + * struct ggml_context * ctx, + * enum ggml_type type, + * int64_t ne0 + * ); + */ +class GGML_new_tensor_1d extends MustCheck { + GGML_new_tensor_1d() { + this.getName() = "ggml_new_tensor_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_tensor_2d( + * struct ggml_context * ctx, + * enum ggml_type type, + * int64_t ne0, + * int64_t ne1 + * ); + */ +class GGML_new_tensor_2d extends MustCheck { + GGML_new_tensor_2d() { + this.getName() = "ggml_new_tensor_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_tensor_3d( + * struct ggml_context * ctx, + * enum ggml_type type, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2 + * ); + */ +class GGML_new_tensor_3d extends MustCheck { + GGML_new_tensor_3d() { + this.getName() = "ggml_new_tensor_3d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_tensor_4d( + * struct ggml_context * ctx, + * enum ggml_type type, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2, + * int64_t ne3 + * ); + */ +class GGML_new_tensor_4d extends MustCheck { + GGML_new_tensor_4d() { + this.getName() = "ggml_new_tensor_4d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_i32( + * struct ggml_context * ctx, + * int32_t value + * ); + */ +class GGML_new_i32 extends MustCheck { + GGML_new_i32() { + this.getName() = "ggml_new_i32" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_new_f32( + * struct ggml_context * ctx, + * float value + * ); + */ +class GGML_new_f32 extends MustCheck { + GGML_new_f32() { + this.getName() = "ggml_new_f32" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_dup_tensor ( + * struct ggml_context * ctx, + * const struct ggml_tensor * src + * ); + */ +class GGML_dup_tensor extends MustCheck { + GGML_dup_tensor() { + this.getName() = "ggml_dup_tensor" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_view_tensor( + * struct ggml_context * ctx, + * struct ggml_tensor * src + * ); + */ +class GGML_view_tensor extends MustCheck { + GGML_view_tensor() { + this.getName() = "ggml_view_tensor" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_get_first_tensor( + * const struct ggml_context * ctx + * ); + */ +class GGML_get_first_tensor extends MustCheck { + GGML_get_first_tensor() { + this.getName() = "ggml_get_first_tensor" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_get_next_tensor ( + * const struct ggml_context * ctx, + * struct ggml_tensor * tensor + * ); + */ +class GGML_get_next_tensor extends MustCheck { + GGML_get_next_tensor() { + this.getName() = "ggml_get_next_tensor" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_get_tensor( + * struct ggml_context * ctx, + * const char * name + * ); + */ +class GGML_get_tensor extends MustCheck { + GGML_get_tensor() { + this.getName() = "ggml_get_tensor" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_zero(struct ggml_tensor * tensor); + */ +class GGML_set_zero extends MustCheck { + GGML_set_zero() { + this.getName() = "ggml_set_zero" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_i32 ( + * struct ggml_tensor * tensor, + * int32_t value + * ); + */ +class GGML_set_i32 extends MustCheck { + GGML_set_i32() { + this.getName() = "ggml_set_i32" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_f32 ( + * struct ggml_tensor * tensor, + * float value + * ); + */ +class GGML_set_f32 extends MustCheck { + GGML_set_f32() { + this.getName() = "ggml_set_f32" + } +} + +/** + * GGML_API void ggml_unravel_index( + * const struct ggml_tensor * tensor, + * int64_t i, + * int64_t * i0, + * int64_t * i1, + * int64_t * i2, + * int64_t * i3 + * ); + */ +class GGML_unravel_index extends Function { + GGML_unravel_index() { + this.getName() = "ggml_unravel_index" + } +} + +/** + * GGML_API int32_t ggml_get_i32_1d(const struct ggml_tensor * tensor, int i); + */ +class GGML_get_i32_1d extends MustUse { + GGML_get_i32_1d() { + this.getName() = "ggml_get_i32_1d" + } +} + +/** + * GGML_API void ggml_set_i32_1d( + * const struct ggml_tensor * tensor, + * int i, + * int32_t value + * ); + */ +class GGML_set_i32_1d extends Function { + GGML_set_i32_1d() { + this.getName() = "ggml_set_i32_1d" + } +} + +/** + * GGML_API int32_t ggml_get_i32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3 + * ); + */ +class GGML_get_i32_nd extends MustUse { + GGML_get_i32_nd() { + this.getName() = "ggml_get_i32_nd" + } +} + +/** + * GGML_API void ggml_set_i32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3, + * int32_t value + * ); + */ +class GGML_set_i32_nd extends Function { + GGML_set_i32_nd() { + this.getName() = "ggml_set_i32_nd" + } +} + +/** + * GGML_API float ggml_get_f32_1d(const struct ggml_tensor * tensor, int i); + */ +class GGML_get_f32_1d extends MustUse { + GGML_get_f32_1d() { + this.getName() = "ggml_get_f32_1d" + } +} + +/** + * GGML_API void ggml_set_f32_1d( + * const struct ggml_tensor * tensor, + * int i, + * float value + * ); + */ +class GGML_set_f32_1d extends Function { + GGML_set_f32_1d() { + this.getName() = "ggml_set_f32_1d" + } +} + +/** + * GGML_API float ggml_get_f32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3 + * ); + */ +class GGML_get_f32_nd extends MustUse { + GGML_get_f32_nd() { + this.getName() = "ggml_get_f32_nd" + } +} + +/** + * GGML_API void ggml_set_f32_nd( + * const struct ggml_tensor * tensor, + * int i0, + * int i1, + * int i2, + * int i3, + * float value + * ); + */ +class GGML_set_f32_nd extends Function { + GGML_set_f32_nd() { + this.getName() = "ggml_set_f32_nd" + } +} + +/** + * GGML_API void * ggml_get_data (const struct ggml_tensor * tensor); + */ +class GGML_get_data extends MustCheck { + GGML_get_data() { + this.getName() = "ggml_get_data" + } +} + +/** + * GGML_API float * ggml_get_data_f32(const struct ggml_tensor * tensor); + */ +class GGML_get_data_f32 extends MustCheck { + GGML_get_data_f32() { + this.getName() = "ggml_get_data_f32" + } +} + +/** + * GGML_API GGML_CALL enum ggml_unary_op ggml_get_unary_op( + * const struct ggml_tensor * tensor + * ); + */ +class GGML_get_unary_op extends MustUse { + GGML_get_unary_op() { + this.getName() = "ggml_get_unary_op" + } +} + +/** + * GGML_API const char * ggml_get_name (const struct ggml_tensor * tensor); + */ +class GGML_get_name extends MustCheck { + GGML_get_name() { + this.getName() = "ggml_get_name" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_name ( + * struct ggml_tensor * tensor, + * const char * name + * ); + */ +class GGML_set_name extends MustCheck { + GGML_set_name() { + this.getName() = "ggml_set_name" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_format_name( + * struct ggml_tensor * tensor, + * const char * fmt, + * ... + * ); + */ +class GGML_format_name extends MustCheck { + GGML_format_name() { + this.getName() = "ggml_format_name" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_dup( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_dup extends MustCheck { + GGML_dup() { + this.getName() = "ggml_dup" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_dup_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_dup_inplace extends MustCheck { + GGML_dup_inplace() { + this.getName() = "ggml_dup_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_add extends MustCheck { + GGML_add() { + this.getName() = "ggml_add" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_add_inplace extends MustCheck { + GGML_add_inplace() { + this.getName() = "ggml_add_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add_cast( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * enum ggml_type type + * ); + */ +class GGML_add_cast extends MustCheck { + GGML_add_cast() { + this.getName() = "ggml_add_cast" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add1( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_add1 extends MustCheck { + GGML_add1() { + this.getName() = "ggml_add1" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add1_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_add1_inplace extends MustCheck { + GGML_add1_inplace() { + this.getName() = "ggml_add1_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_acc( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t nb1, + * size_t nb2, + * size_t nb3, + * size_t offset + * ); + */ +class GGML_acc extends MustCheck { + GGML_acc() { + this.getName() = "ggml_acc" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_acc_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t nb1, + * size_t nb2, + * size_t nb3, + * size_t offset + * ); + */ +class GGML_acc_inplace extends MustCheck { + GGML_acc_inplace() { + this.getName() = "ggml_acc_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sub( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_sub extends MustCheck { + GGML_sub() { + this.getName() = "ggml_sub" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sub_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_sub_inplace extends MustCheck { + GGML_sub_inplace() { + this.getName() = "ggml_sub_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_mul( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_mul extends MustCheck { + GGML_mul() { + this.getName() = "ggml_mul" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_mul_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_mul_inplace extends MustCheck { + GGML_mul_inplace() { + this.getName() = "ggml_mul_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_div( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_div extends MustCheck { + GGML_div() { + this.getName() = "ggml_div" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_div_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_div_inplace extends MustCheck { + GGML_div_inplace() { + this.getName() = "ggml_div_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sqr( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sqr extends MustCheck { + GGML_sqr() { + this.getName() = "ggml_sqr" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sqr_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sqr_inplace extends MustCheck { + GGML_sqr_inplace() { + this.getName() = "ggml_sqr_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sqrt( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sqrt extends MustCheck { + GGML_sqrt() { + this.getName() = "ggml_sqrt" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sqrt_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sqrt_inplace extends MustCheck { + GGML_sqrt_inplace() { + this.getName() = "ggml_sqrt_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_log( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_log extends MustCheck { + GGML_log() { + this.getName() = "ggml_log" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_log_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_log_inplace extends MustCheck { + GGML_log_inplace() { + this.getName() = "ggml_log_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sum( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sum extends MustCheck { + GGML_sum() { + this.getName() = "ggml_sum" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sum_rows( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sum_rows extends MustCheck { + GGML_sum_rows() { + this.getName() = "ggml_sum_rows" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_mean( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_mean extends MustCheck { + GGML_mean() { + this.getName() = "ggml_mean" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_argmax( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_argmax extends MustCheck { + GGML_argmax() { + this.getName() = "ggml_argmax" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_repeat( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_repeat extends MustCheck { + GGML_repeat() { + this.getName() = "ggml_repeat" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_repeat_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_repeat_back extends MustCheck { + GGML_repeat_back() { + this.getName() = "ggml_repeat_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_concat( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_concat extends MustCheck { + GGML_concat() { + this.getName() = "ggml_concat" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_abs( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_abs extends MustCheck { + GGML_abs() { + this.getName() = "ggml_abs" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_abs_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_abs_inplace extends MustCheck { + GGML_abs_inplace() { + this.getName() = "ggml_abs_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sgn( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sgn extends MustCheck { + GGML_sgn() { + this.getName() = "ggml_sgn" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sgn_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sgn_inplace extends MustCheck { + GGML_sgn_inplace() { + this.getName() = "ggml_sgn_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_neg( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_neg extends MustCheck { + GGML_neg() { + this.getName() = "ggml_neg" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_neg_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_neg_inplace extends MustCheck { + GGML_neg_inplace() { + this.getName() = "ggml_neg_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_step( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_step extends MustCheck { + GGML_step() { + this.getName() = "ggml_step" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_step_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_step_inplace extends MustCheck { + GGML_step_inplace() { + this.getName() = "ggml_step_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_tanh( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_tanh extends MustCheck { + GGML_tanh() { + this.getName() = "ggml_tanh" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_tanh_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_tanh_inplace extends MustCheck { + GGML_tanh_inplace() { + this.getName() = "ggml_tanh_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_elu( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_elu extends MustCheck { + GGML_elu() { + this.getName() = "ggml_elu" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_elu_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_elu_inplace extends MustCheck { + GGML_elu_inplace() { + this.getName() = "ggml_elu_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_relu( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_relu extends MustCheck { + GGML_relu() { + this.getName() = "ggml_relu" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sigmoid( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sigmoid extends MustCheck { + GGML_sigmoid() { + this.getName() = "ggml_sigmoid" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_leaky_relu( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float negative_slope, + * bool inplace + * ); + */ +class GGML_leaky_relu extends MustCheck { + GGML_leaky_relu() { + this.getName() = "ggml_leaky_relu" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_relu_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_relu_inplace extends MustCheck { + GGML_relu_inplace() { + this.getName() = "ggml_relu_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_sigmoid_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_sigmoid_inplace extends MustCheck { + GGML_sigmoid_inplace() { + this.getName() = "ggml_sigmoid_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_gelu( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_gelu extends MustCheck { + GGML_gelu() { + this.getName() = "ggml_gelu" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_gelu_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_gelu_inplace extends MustCheck { + GGML_gelu_inplace() { + this.getName() = "ggml_gelu_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_gelu_quick( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_gelu_quick extends MustCheck { + GGML_gelu_quick() { + this.getName() = "ggml_gelu_quick" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_gelu_quick_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_gelu_quick_inplace extends MustCheck { + GGML_gelu_quick_inplace() { + this.getName() = "ggml_gelu_quick_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_silu( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_silu extends MustCheck { + GGML_silu() { + this.getName() = "ggml_silu" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_silu_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_silu_inplace extends MustCheck { + GGML_silu_inplace() { + this.getName() = "ggml_silu_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_silu_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_silu_back extends MustCheck { + GGML_silu_back() { + this.getName() = "ggml_silu_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_hardswish( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_hardswish extends MustCheck { + GGML_hardswish() { + this.getName() = "ggml_hardswish" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_hardsigmoid( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_hardsigmoid extends MustCheck { + GGML_hardsigmoid() { + this.getName() = "ggml_hardsigmoid" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_norm( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float eps + * ); + */ +class GGML_norm extends MustCheck { + GGML_norm() { + this.getName() = "ggml_norm" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_norm_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float eps + * ); + */ +class GGML_norm_inplace extends MustCheck { + GGML_norm_inplace() { + this.getName() = "ggml_norm_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rms_norm( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float eps + * ); + */ +class GGML_rms_norm extends MustCheck { + GGML_rms_norm() { + this.getName() = "ggml_rms_norm" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rms_norm_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float eps + * ); + */ +class GGML_rms_norm_inplace extends MustCheck { + GGML_rms_norm_inplace() { + this.getName() = "ggml_rms_norm_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_group_norm( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int n_groups + * ); + */ +class GGML_group_norm extends MustCheck { + GGML_group_norm() { + this.getName() = "ggml_group_norm" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_group_norm_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int n_groups + * ); + */ +class GGML_group_norm_inplace extends MustCheck { + GGML_group_norm_inplace() { + this.getName() = "ggml_group_norm_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rms_norm_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * float eps + * ); + */ +class GGML_rms_norm_back extends MustCheck { + GGML_rms_norm_back() { + this.getName() = "ggml_rms_norm_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_mul_mat( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_mul_mat extends MustCheck { + GGML_mul_mat() { + this.getName() = "ggml_mul_mat" + } +} + +/** + * GGML_API void ggml_mul_mat_set_prec( + * struct ggml_tensor * a, + * enum ggml_prec prec + * ); + */ +class GGML_mul_mat_set_prec extends Function { + GGML_mul_mat_set_prec() { + this.getName() = "ggml_mul_mat_set_prec" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_mul_mat_id( + * struct ggml_context * ctx, + * struct ggml_tensor * as, + * struct ggml_tensor * ids, + * int id, + * struct ggml_tensor * b + * ); + */ +class GGML_mul_mat_id extends MustCheck { + GGML_mul_mat_id() { + this.getName() = "ggml_mul_mat_id" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_out_prod( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_out_prod extends MustCheck { + GGML_out_prod() { + this.getName() = "ggml_out_prod" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_scale( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float s + * ); + */ +class GGML_scale extends MustCheck { + GGML_scale() { + this.getName() = "ggml_scale" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_scale_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float s + * ); + */ +class GGML_scale_inplace extends MustCheck { + GGML_scale_inplace() { + this.getName() = "ggml_scale_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t nb1, + * size_t nb2, + * size_t nb3, + * size_t offset + * ); + */ +class GGML_set extends MustCheck { + GGML_set() { + this.getName() = "ggml_set" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t nb1, + * size_t nb2, + * size_t nb3, + * size_t offset + * ); + */ +class GGML_set_inplace extends MustCheck { + GGML_set_inplace() { + this.getName() = "ggml_set_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t offset + * ); + */ +class GGML_set_1d extends MustCheck { + GGML_set_1d() { + this.getName() = "ggml_set_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_1d_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t offset + * ); + */ +class GGML_set_1d_inplace extends MustCheck { + GGML_set_1d_inplace() { + this.getName() = "ggml_set_1d_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t nb1, + * size_t offset + * ); + */ +class GGML_set_2d extends MustCheck { + GGML_set_2d() { + this.getName() = "ggml_set_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_set_2d_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * size_t nb1, + * size_t offset + * ); + */ +class GGML_set_2d_inplace extends MustCheck { + GGML_set_2d_inplace() { + this.getName() = "ggml_set_2d_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cpy( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_cpy extends MustCheck { + GGML_cpy() { + this.getName() = "ggml_cpy" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cast( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * enum ggml_type type + * ); + */ +class GGML_cast extends MustCheck { + GGML_cast() { + this.getName() = "ggml_cast" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cont( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_cont extends MustCheck { + GGML_cont() { + this.getName() = "ggml_cont" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cont_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0 + * ); + */ +class GGML_cont_1d extends MustCheck { + GGML_cont_1d() { + this.getName() = "ggml_cont_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cont_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1 + * ); + */ +class GGML_cont_2d extends MustCheck { + GGML_cont_2d() { + this.getName() = "ggml_cont_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cont_3d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2 + * ); + */ +class GGML_cont_3d extends MustCheck { + GGML_cont_3d() { + this.getName() = "ggml_cont_3d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_cont_4d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2, + * int64_t ne3 + * ); + */ +class GGML_cont_4d extends MustCheck { + GGML_cont_4d() { + this.getName() = "ggml_cont_4d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_reshape( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_reshape extends MustCheck { + GGML_reshape() { + this.getName() = "ggml_reshape" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_reshape_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0 + * ); + */ +class GGML_reshape_1d extends MustCheck { + GGML_reshape_1d() { + this.getName() = "ggml_reshape_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_reshape_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1 + * ); + */ +class GGML_reshape_2d extends MustCheck { + GGML_reshape_2d() { + this.getName() = "ggml_reshape_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_reshape_3d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2 + * ); + */ +class GGML_reshape_3d extends MustCheck { + GGML_reshape_3d() { + this.getName() = "ggml_reshape_3d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_reshape_4d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2, + * int64_t ne3 + * ); + */ +class GGML_reshape_4d extends MustCheck { + GGML_reshape_4d() { + this.getName() = "ggml_reshape_4d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_view_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * size_t offset + * ); + */ +class GGML_view_1d extends MustCheck { + GGML_view_1d() { + this.getName() = "ggml_view_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_view_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * size_t nb1, + * // row stride in bytes size_t offset + * ); + */ +class GGML_view_2d extends MustCheck { + GGML_view_2d() { + this.getName() = "ggml_view_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_view_3d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2, + * size_t nb1, + * // row stride in bytes size_t nb2, + * // slice stride in bytes size_t offset + * ); + */ +class GGML_view_3d extends MustCheck { + GGML_view_3d() { + this.getName() = "ggml_view_3d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_view_4d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int64_t ne0, + * int64_t ne1, + * int64_t ne2, + * int64_t ne3, + * size_t nb1, + * // row stride in bytes size_t nb2, + * // slice stride in bytes size_t nb3, + * size_t offset + * ); + */ +class GGML_view_4d extends MustCheck { + GGML_view_4d() { + this.getName() = "ggml_view_4d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_permute( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int axis0, + * int axis1, + * int axis2, + * int axis3 + * ); + */ +class GGML_permute extends MustCheck { + GGML_permute() { + this.getName() = "ggml_permute" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_transpose( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_transpose extends MustCheck { + GGML_transpose() { + this.getName() = "ggml_transpose" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_get_rows( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_get_rows extends MustCheck { + GGML_get_rows() { + this.getName() = "ggml_get_rows" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_get_rows_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * struct ggml_tensor * c + * ); + */ +class GGML_get_rows_back extends MustCheck { + GGML_get_rows_back() { + this.getName() = "ggml_get_rows_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_diag( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_diag extends MustCheck { + GGML_diag() { + this.getName() = "ggml_diag" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_diag_mask_inf( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int n_past + * ); + */ +class GGML_diag_mask_inf extends MustCheck { + GGML_diag_mask_inf() { + this.getName() = "ggml_diag_mask_inf" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_diag_mask_inf_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int n_past + * ); + */ +class GGML_diag_mask_inf_inplace extends MustCheck { + GGML_diag_mask_inf_inplace() { + this.getName() = "ggml_diag_mask_inf_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_diag_mask_zero( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int n_past + * ); + */ +class GGML_diag_mask_zero extends MustCheck { + GGML_diag_mask_zero() { + this.getName() = "ggml_diag_mask_zero" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_diag_mask_zero_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int n_past + * ); + */ +class GGML_diag_mask_zero_inplace extends MustCheck { + GGML_diag_mask_zero_inplace() { + this.getName() = "ggml_diag_mask_zero_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_soft_max( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_soft_max extends MustCheck { + GGML_soft_max() { + this.getName() = "ggml_soft_max" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_soft_max_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a + * ); + */ +class GGML_soft_max_inplace extends MustCheck { + GGML_soft_max_inplace() { + this.getName() = "ggml_soft_max_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_soft_max_ext( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * mask, + * struct ggml_tensor * pos, + * float scale, + * float max_bias + * ); + */ +class GGML_soft_max_ext extends MustCheck { + GGML_soft_max_ext() { + this.getName() = "ggml_soft_max_ext" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_soft_max_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_soft_max_back extends MustCheck { + GGML_soft_max_back() { + this.getName() = "ggml_soft_max_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_soft_max_back_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_soft_max_back_inplace extends MustCheck { + GGML_soft_max_back_inplace() { + this.getName() = "ggml_soft_max_back_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rope( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int n_dims, + * int mode, + * int n_ctx + * ); + */ +class GGML_rope extends MustCheck { + GGML_rope() { + this.getName() = "ggml_rope" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rope_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int n_dims, + * int mode, + * int n_ctx + * ); + */ +class GGML_rope_inplace extends MustCheck { + GGML_rope_inplace() { + this.getName() = "ggml_rope_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rope_custom( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int n_dims, + * int mode, + * int n_ctx, + * int n_orig_ctx, + * float freq_base, + * float freq_scale, + * float ext_factor, + * float attn_factor, + * float beta_fast, + * float beta_slow + * ); + */ +class GGML_rope_custom extends MustCheck { + GGML_rope_custom() { + this.getName() = "ggml_rope_custom" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rope_custom_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int n_dims, + * int mode, + * int n_ctx, + * int n_orig_ctx, + * float freq_base, + * float freq_scale, + * float ext_factor, + * float attn_factor, + * float beta_fast, + * float beta_slow + * ); + */ +class GGML_rope_custom_inplace extends MustCheck { + GGML_rope_custom_inplace() { + this.getName() = "ggml_rope_custom_inplace" + } +} + +/** + * GGML_CALL void ggml_rope_yarn_corr_dims( + * int n_dims, + * int n_orig_ctx, + * float freq_base, + * float beta_fast, + * float beta_slow, + * float dims[2] + * ); + */ +class GGML_rope_yarn_corr_dims extends Function { + GGML_rope_yarn_corr_dims() { + this.getName() = "ggml_rope_yarn_corr_dims" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rope_xpos_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int n_dims, + * float base, + * bool down + * ); + */ +class GGML_rope_xpos_inplace extends MustCheck { + GGML_rope_xpos_inplace() { + this.getName() = "ggml_rope_xpos_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_rope_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int n_dims, + * int mode, + * int n_ctx, + * int n_orig_ctx, + * float freq_base, + * float freq_scale, + * float ext_factor, + * float attn_factor, + * float beta_fast, + * float beta_slow, + * float xpos_base, + * bool xpos_down + * ); + */ +class GGML_rope_back extends MustCheck { + GGML_rope_back() { + this.getName() = "ggml_rope_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_clamp( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * float min, + * float max + * ); + */ +class GGML_clamp extends MustCheck { + GGML_clamp() { + this.getName() = "ggml_clamp" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_im2col( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int s0, + * int s1, + * int p0, + * int p1, + * int d0, + * int d1, + * bool is_2D, + * enum ggml_type dst_type + * ); + */ +class GGML_im2col extends MustCheck { + GGML_im2col() { + this.getName() = "ggml_im2col" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_depthwise_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int s0, + * int s1, + * int p0, + * int p1, + * int d0, + * int d1 + * ); + */ +class GGML_conv_depthwise_2d extends MustCheck { + GGML_conv_depthwise_2d() { + this.getName() = "ggml_conv_depthwise_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int s0, + * // stride int p0, + * // padding int d0 + * ); + */ +class GGML_conv_1d extends MustCheck { + GGML_conv_1d() { + this.getName() = "ggml_conv_1d" + } +} + +/** + * GGML_API struct ggml_tensor* ggml_conv_1d_ph( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int s, + * int d + * ); + */ +class GGML_conv_1d_ph extends MustCheck { + GGML_conv_1d_ph() { + this.getName() = "ggml_conv_1d_ph" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_transpose_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int s0, + * int p0, + * int d0 + * ); + */ +class GGML_conv_transpose_1d extends MustCheck { + GGML_conv_transpose_1d() { + this.getName() = "ggml_conv_transpose_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int s0, + * int s1, + * int p0, + * int p1, + * int d0, + * int d1 + * ); + */ +class GGML_conv_2d extends MustCheck { + GGML_conv_2d() { + this.getName() = "ggml_conv_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_2d_sk_p0( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_conv_2d_sk_p0 extends MustCheck { + GGML_conv_2d_sk_p0() { + this.getName() = "ggml_conv_2d_sk_p0" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_2d_s1_ph( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); + */ +class GGML_conv_2d_s1_ph extends MustCheck { + GGML_conv_2d_s1_ph() { + this.getName() = "ggml_conv_2d_s1_ph" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_conv_transpose_2d_p0( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * int stride + * ); + */ +class GGML_conv_transpose_2d_p0 extends MustCheck { + GGML_conv_transpose_2d_p0() { + this.getName() = "ggml_conv_transpose_2d_p0" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_pool_1d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * enum ggml_op_pool op, + * int k0, + * // kernel size int s0, + * // stride int p0 + * ); + */ +class GGML_pool_1d extends MustCheck { + GGML_pool_1d() { + this.getName() = "ggml_pool_1d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_pool_2d( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * enum ggml_op_pool op, + * int k0, + * int k1, + * int s0, + * int s1, + * float p0, + * float p1 + * ); + */ +class GGML_pool_2d extends MustCheck { + GGML_pool_2d() { + this.getName() = "ggml_pool_2d" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_upscale( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int scale_factor + * ); + */ +class GGML_upscale extends MustCheck { + GGML_upscale() { + this.getName() = "ggml_upscale" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_pad( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int p0, + * int p1, + * int p2, + * int p3 + * ); + */ +class GGML_pad extends MustCheck { + GGML_pad() { + this.getName() = "ggml_pad" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_timestep_embedding( + * struct ggml_context * ctx, + * struct ggml_tensor * timesteps, + * int dim, + * int max_period + * ); + */ +class GGML_timestep_embedding extends MustCheck { + GGML_timestep_embedding() { + this.getName() = "ggml_timestep_embedding" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_argsort( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * enum ggml_sort_order order + * ); + */ +class GGML_argsort extends MustCheck { + GGML_argsort() { + this.getName() = "ggml_argsort" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_arange( + * struct ggml_context * ctx, + * float start, + * float stop, + * float step + * ); + */ +class GGML_arange extends MustCheck { + GGML_arange() { + this.getName() = "ggml_arange" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_top_k( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int k + * ); + */ +class GGML_top_k extends MustCheck { + GGML_top_k() { + this.getName() = "ggml_top_k" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_flash_attn( + * struct ggml_context * ctx, + * struct ggml_tensor * q, + * struct ggml_tensor * k, + * struct ggml_tensor * v, + * bool masked + * ); + */ +class GGML_flash_attn extends MustCheck { + GGML_flash_attn() { + this.getName() = "ggml_flash_attn" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_flash_attn_back( + * struct ggml_context * ctx, + * struct ggml_tensor * q, + * struct ggml_tensor * k, + * struct ggml_tensor * v, + * struct ggml_tensor * d, + * bool masked + * ); + */ +class GGML_flash_attn_back extends MustCheck { + GGML_flash_attn_back() { + this.getName() = "ggml_flash_attn_back" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_flash_ff( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b0, + * struct ggml_tensor * b1, + * struct ggml_tensor * c0, + * struct ggml_tensor * c1 + * ); + */ +class GGML_flash_ff extends MustCheck { + GGML_flash_ff() { + this.getName() = "ggml_flash_ff" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_ssm_conv( + * struct ggml_context * ctx, + * struct ggml_tensor * s, + * struct ggml_tensor * x, + * struct ggml_tensor * c, + * struct ggml_tensor * sq + * ); + */ +class GGML_ssm_conv extends MustCheck { + GGML_ssm_conv() { + this.getName() = "ggml_ssm_conv" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_ssm_scan( + * struct ggml_context * ctx, + * struct ggml_tensor * s, + * struct ggml_tensor * x, + * struct ggml_tensor * dt, + * struct ggml_tensor * A, + * struct ggml_tensor * B, + * struct ggml_tensor * C, + * struct ggml_tensor * sq + * ); + */ +class GGML_ssm_scan extends MustCheck { + GGML_ssm_scan() { + this.getName() = "ggml_ssm_scan" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_win_part( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int w + * ); + */ +class GGML_win_part extends MustCheck { + GGML_win_part() { + this.getName() = "ggml_win_part" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_win_unpart( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int w0, + * int h0, + * int w + * ); + */ +class GGML_win_unpart extends MustCheck { + GGML_win_unpart() { + this.getName() = "ggml_win_unpart" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_unary( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * enum ggml_unary_op op + * ); + */ +class GGML_unary extends MustCheck { + GGML_unary() { + this.getName() = "ggml_unary" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_unary_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * enum ggml_unary_op op + * ); + */ +class GGML_unary_inplace extends MustCheck { + GGML_unary_inplace() { + this.getName() = "ggml_unary_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_get_rel_pos( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * int qh, + * int kh + * ); + */ +class GGML_get_rel_pos extends MustCheck { + GGML_get_rel_pos() { + this.getName() = "ggml_get_rel_pos" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add_rel_pos( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * pw, + * struct ggml_tensor * ph + * ); + */ +class GGML_add_rel_pos extends MustCheck { + GGML_add_rel_pos() { + this.getName() = "ggml_add_rel_pos" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_add_rel_pos_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * pw, + * struct ggml_tensor * ph + * ); + */ +class GGML_add_rel_pos_inplace extends MustCheck { + GGML_add_rel_pos_inplace() { + this.getName() = "ggml_add_rel_pos_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_map_custom1( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * ggml_custom1_op_t fun, + * int n_tasks, + * void * userdata + * ); + */ +class GGML_map_custom1 extends MustCheck { + GGML_map_custom1() { + this.getName() = "ggml_map_custom1" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_map_custom1_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * ggml_custom1_op_t fun, + * int n_tasks, + * void * userdata + * ); + */ +class GGML_map_custom1_inplace extends MustCheck { + GGML_map_custom1_inplace() { + this.getName() = "ggml_map_custom1_inplace" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_map_custom2( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * ggml_custom2_op_t fun, + * int n_tasks, + * void * userdata + * ); + */ +class GGML_map_custom2 extends MustCheck { + GGML_map_custom2() { + this.getName() = "ggml_map_custom2" + } +} + +/** + * GGML_API struct ggml_tensor * ggml_map_custom2_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * ggml_custom2_op_t fun, + * int n_tasks, + * void * userdata + * ); */ -class GGML_is_vector extends MustUse { - GGML_is_vector() { - this.getName() = "ggml_is_vector" +class GGML_map_custom2_inplace extends MustCheck { + GGML_map_custom2_inplace() { + this.getName() = "ggml_map_custom2_inplace" } } /** - * GGML_API bool ggml_is_matrix (const struct ggml_tensor * tensor); + * GGML_API struct ggml_tensor * ggml_map_custom3( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * struct ggml_tensor * c, + * ggml_custom3_op_t fun, + * int n_tasks, + * void * userdata + * ); */ -class GGML_is_matrix extends MustUse { - GGML_is_matrix() { - this.getName() = "ggml_is_matrix" +class GGML_map_custom3 extends MustCheck { + GGML_map_custom3() { + this.getName() = "ggml_map_custom3" } } /** - * GGML_API bool ggml_is_3d (const struct ggml_tensor * tensor); + * GGML_API struct ggml_tensor * ggml_map_custom3_inplace( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * struct ggml_tensor * c, + * ggml_custom3_op_t fun, + * int n_tasks, + * void * userdata + * ); */ -class GGML_is_3d extends MustUse { - GGML_is_3d() { - this.getName() = "ggml_is_3d" +class GGML_map_custom3_inplace extends MustCheck { + GGML_map_custom3_inplace() { + this.getName() = "ggml_map_custom3_inplace" } } /** - * GGML_API int ggml_n_dims (const struct ggml_tensor * tensor); + * GGML_API struct ggml_tensor * ggml_cross_entropy_loss( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b + * ); */ -class GGML_n_dims extends MustUse { - GGML_n_dims() { - this.getName() = "ggml_n_dims" +class GGML_cross_entropy_loss extends MustCheck { + GGML_cross_entropy_loss() { + this.getName() = "ggml_cross_entropy_loss" } } /** - * GGML_API bool ggml_are_same_shape( - * const struct ggml_tensor * t0, - * const struct ggml_tensor * t1 + * GGML_API struct ggml_tensor * ggml_cross_entropy_loss_back( + * struct ggml_context * ctx, + * struct ggml_tensor * a, + * struct ggml_tensor * b, + * struct ggml_tensor * c * ); */ -class GGML_are_same_shape extends MustUse { - GGML_are_same_shape() { - this.getName() = "ggml_are_same_shape" +class GGML_cross_entropy_loss_back extends MustCheck { + GGML_cross_entropy_loss_back() { + this.getName() = "ggml_cross_entropy_loss_back" } } /** - * GGML_API size_t ggml_tensor_overhead(void); + * GGML_API void ggml_set_param( + * struct ggml_context * ctx, + * struct ggml_tensor * tensor + * ); */ -class GGML_tensor_overhead extends MustUse { - GGML_tensor_overhead() { - this.getName() = "ggml_tensor_overhead" +class GGML_set_param extends Function { + GGML_set_param() { + this.getName() = "ggml_set_param" } } /** - * struct ggml_context * ggml_init(struct ggml_init_params params); + * GGML_API void ggml_build_forward_expand ( + * struct ggml_cgraph * cgraph, + * struct ggml_tensor * tensor + * ); */ -class GGML_init extends Alloc { - GGML_init() { - this.getName() = "ggml_init" +class GGML_build_forward_expand extends Function { + GGML_build_forward_expand() { + this.getName() = "ggml_build_forward_expand" } } /** - * GGML_API void ggml_free(struct ggml_context * ctx); + * GGML_API void ggml_build_backward_expand( + * struct ggml_context * ctx, + * struct ggml_cgraph * gf, + * struct ggml_cgraph * gb, + * bool keep + * ); */ -class GGML_free extends Free { - GGML_free() { - this.getName() = "ggml_free" +class GGML_build_backward_expand extends Function { + GGML_build_backward_expand() { + this.getName() = "ggml_build_backward_expand" } } /** - * GGML_API size_t ggml_used_mem(const struct ggml_context * ctx); + * GGML_API struct ggml_cgraph * ggml_new_graph (struct ggml_context * ctx); */ -class GGML_used_mem extends MustUse { - GGML_used_mem() { - this.getName() = "ggml_used_mem" +class GGML_new_graph extends MustCheck { + GGML_new_graph() { + this.getName() = "ggml_new_graph" } } /** - * GGML_API size_t ggml_set_scratch ( + * GGML_API struct ggml_cgraph * ggml_new_graph_custom ( * struct ggml_context * ctx, - * struct ggml_scratch scratch + * size_t size, + * bool grads * ); */ -class GGML_set_scratch extends MustUse { - GGML_set_scratch() { - this.getName() = "ggml_set_scratch" +class GGML_new_graph_custom extends MustCheck { + GGML_new_graph_custom() { + this.getName() = "ggml_new_graph_custom" } } /** - * GGML_API bool ggml_get_no_alloc(struct ggml_context * ctx); + * GGML_API struct ggml_cgraph * ggml_graph_dup ( + * struct ggml_context * ctx, + * struct ggml_cgraph * cgraph + * ); */ -class GGML_get_no_alloc extends MustUse { - GGML_get_no_alloc() { - this.getName() = "ggml_get_no_alloc" +class GGML_graph_dup extends MustCheck { + GGML_graph_dup() { + this.getName() = "ggml_graph_dup" } } /** - * GGML_API void ggml_set_no_alloc(struct ggml_context * ctx, bool no_alloc); + * GGML_API struct ggml_cgraph ggml_graph_view ( + * struct ggml_cgraph * cgraph, + * int i0, + * int i1 + * ); */ -class GGML_set_no_alloc extends Function { - GGML_set_no_alloc() { - this.getName() = "ggml_set_no_alloc" +class GGML_graph_view extends MustUse { + GGML_graph_view() { + this.getName() = "ggml_graph_view" } } /** - * GGML_API size_t ggml_get_mem_size (const struct ggml_context * ctx); + * GGML_API void ggml_graph_cpy ( + * struct ggml_cgraph * src, + * struct ggml_cgraph * dst + * ); */ -class GGML_get_mem_size extends MustUse { - GGML_get_mem_size() { - this.getName() = "ggml_get_mem_size" +class GGML_graph_cpy extends Function { + GGML_graph_cpy() { + this.getName() = "ggml_graph_cpy" } } /** - * GGML_API size_t ggml_get_max_tensor_size(const struct ggml_context * ctx); + * GGML_API void ggml_graph_reset (struct ggml_cgraph * cgraph); */ -class GGML_get_max_tensor_size extends MustUse { - GGML_get_max_tensor_size() { - this.getName() = "ggml_get_max_tensor_size" +class GGML_graph_reset extends Function { + GGML_graph_reset() { + this.getName() = "ggml_graph_reset" } } /** - * GGML_API void ggml_unravel_index( - * const struct ggml_tensor * tensor, - * int64_t i, - * int64_t * i0, - * int64_t * i1, - * int64_t * i2, - * int64_t * i3 - * ); + * GGML_API void ggml_graph_clear (struct ggml_cgraph * cgraph); */ -class GGML_unravel_index extends Function { - GGML_unravel_index() { - this.getName() = "ggml_unravel_index" +class GGML_graph_clear extends Function { + GGML_graph_clear() { + this.getName() = "ggml_graph_clear" } } /** - * GGML_API int32_t ggml_get_i32_1d(const struct ggml_tensor * tensor, int i); + * GGML_API size_t ggml_graph_overhead(void); */ -class GGML_get_i32_1d extends MustUse { - GGML_get_i32_1d() { - this.getName() = "ggml_get_i32_1d" +class GGML_graph_overhead extends MustUse { + GGML_graph_overhead() { + this.getName() = "ggml_graph_overhead" } } /** - * GGML_API void ggml_set_i32_1d( - * const struct ggml_tensor * tensor, - * int i, - * int32_t value - * ); + * GGML_API size_t ggml_graph_overhead_custom(size_t size, bool grads); */ -class GGML_set_i32_1d extends Function { - GGML_set_i32_1d() { - this.getName() = "ggml_set_i32_1d" +class GGML_graph_overhead_custom extends MustUse { + GGML_graph_overhead_custom() { + this.getName() = "ggml_graph_overhead_custom" } } /** - * GGML_API int32_t ggml_get_i32_nd( - * const struct ggml_tensor * tensor, - * int i0, - * int i1, - * int i2, - * int i3 + * GGML_API struct ggml_cplan ggml_graph_plan ( + * const struct ggml_cgraph * cgraph, + * int n_threads * ); */ -class GGML_get_i32_nd extends MustUse { - GGML_get_i32_nd() { - this.getName() = "ggml_get_i32_nd" +class GGML_graph_plan extends MustUse { + GGML_graph_plan() { + this.getName() = "ggml_graph_plan" } } /** - * GGML_API void ggml_set_i32_nd( - * const struct ggml_tensor * tensor, - * int i0, - * int i1, - * int i2, - * int i3, - * int32_t value + * GGML_API enum ggml_status ggml_graph_compute ( + * struct ggml_cgraph * cgraph, + * struct ggml_cplan * cplan * ); */ -class GGML_set_i32_nd extends Function { - GGML_set_i32_nd() { - this.getName() = "ggml_set_i32_nd" +class GGML_graph_compute extends MustUse { + GGML_graph_compute() { + this.getName() = "ggml_graph_compute" } } /** - * GGML_API float ggml_get_f32_1d(const struct ggml_tensor * tensor, int i); + * GGML_API enum ggml_status ggml_graph_compute_with_ctx( + * struct ggml_context * ctx, + * struct ggml_cgraph * cgraph, + * int n_threads + * ); */ -class GGML_get_f32_1d extends MustUse { - GGML_get_f32_1d() { - this.getName() = "ggml_get_f32_1d" +class GGML_graph_compute_with_ctx extends MustUse { + GGML_graph_compute_with_ctx() { + this.getName() = "ggml_graph_compute_with_ctx" } } /** - * GGML_API void ggml_set_f32_1d( - * const struct ggml_tensor * tensor, - * int i, - * float value + * GGML_API struct ggml_tensor * ggml_graph_get_tensor( + * struct ggml_cgraph * cgraph, + * const char * name * ); */ -class GGML_set_f32_1d extends Function { - GGML_set_f32_1d() { - this.getName() = "ggml_set_f32_1d" +class GGML_graph_get_tensor extends MustCheck { + GGML_graph_get_tensor() { + this.getName() = "ggml_graph_get_tensor" } } /** - * GGML_API float ggml_get_f32_nd( - * const struct ggml_tensor * tensor, - * int i0, - * int i1, - * int i2, - * int i3 + * GGML_API void ggml_graph_export( + * const struct ggml_cgraph * cgraph, + * const char * fname * ); */ -class GGML_get_f32_nd extends MustUse { - GGML_get_f32_nd() { - this.getName() = "ggml_get_f32_nd" +class GGML_graph_export extends Function { + GGML_graph_export() { + this.getName() = "ggml_graph_export" } } /** - * GGML_API void ggml_set_f32_nd( - * const struct ggml_tensor * tensor, - * int i0, - * int i1, - * int i2, - * int i3, - * float value + * GGML_API struct ggml_cgraph * ggml_graph_import( + * const char * fname, + * struct ggml_context ** ctx_data, + * struct ggml_context ** ctx_eval * ); */ -class GGML_set_f32_nd extends Function { - GGML_set_f32_nd() { - this.getName() = "ggml_set_f32_nd" +class GGML_graph_import extends MustCheck { + GGML_graph_import() { + this.getName() = "ggml_graph_import" } } /** - * GGML_API GGML_CALL enum ggml_unary_op ggml_get_unary_op( - * const struct ggml_tensor * tensor - * ); + * GGML_API void ggml_graph_print(const struct ggml_cgraph * cgraph); */ -class GGML_get_unary_op extends MustUse { - GGML_get_unary_op() { - this.getName() = "ggml_get_unary_op" +class GGML_graph_print extends Function { + GGML_graph_print() { + this.getName() = "ggml_graph_print" } } /** - * GGML_API void ggml_mul_mat_set_prec( - * struct ggml_tensor * a, - * enum ggml_prec prec + * GGML_API void ggml_graph_dump_dot( + * const struct ggml_cgraph * gb, + * const struct ggml_cgraph * gf, + * const char * filename * ); */ -class GGML_mul_mat_set_prec extends Function { - GGML_mul_mat_set_prec() { - this.getName() = "ggml_mul_mat_set_prec" +class GGML_graph_dump_dot extends Function { + GGML_graph_dump_dot() { + this.getName() = "ggml_graph_dump_dot" } } /** - * GGML_CALL void ggml_rope_yarn_corr_dims( - * int n_dims, - * int n_orig_ctx, - * float freq_base, - * float beta_fast, - * float beta_slow, - * float dims[2] + * GGML_API void ggml_build_backward_gradient_checkpointing( + * struct ggml_context * ctx, + * struct ggml_cgraph * gf, + * struct ggml_cgraph * gb, + * struct ggml_cgraph * gb_tmp, + * struct ggml_tensor * * checkpoints, + * int n_checkpoints * ); */ -class GGML_rope_yarn_corr_dims extends Function { - GGML_rope_yarn_corr_dims() { - this.getName() = "ggml_rope_yarn_corr_dims" +class GGML_build_backward_gradient_checkpointing extends Function { + GGML_build_backward_gradient_checkpointing() { + this.getName() = "ggml_build_backward_gradient_checkpointing" } } @@ -606,7 +3208,7 @@ class GGML_opt_default_params extends MustUse { /** * GGML_API enum ggml_opt_result ggml_opt( - * struct ggml_context * ctx, + * struct ggml_context * ctx, * struct ggml_opt_params params, * struct ggml_tensor * f * ); @@ -619,7 +3221,7 @@ class GGML_opt extends MustUse { /** * GGML_API void ggml_opt_init( - * struct ggml_context * ctx, + * struct ggml_context * ctx, * struct ggml_opt_context * opt, * struct ggml_opt_params params, * int64_t nx @@ -633,7 +3235,7 @@ class GGML_opt_init extends Function { /** * GGML_API enum ggml_opt_result ggml_opt_resume( - * struct ggml_context * ctx, + * struct ggml_context * ctx, * struct ggml_opt_context * opt, * struct ggml_tensor * f * ); @@ -646,7 +3248,7 @@ class GGML_opt_resume extends MustUse { /** * GGML_API enum ggml_opt_result ggml_opt_resume_g( - * struct ggml_context * ctx, + * struct ggml_context * ctx, * struct ggml_opt_context * opt, * struct ggml_tensor * f, * struct ggml_cgraph * gf, @@ -708,7 +3310,7 @@ class GGML_quantize_requires_imatrix extends MustUse { /** * GGML_API size_t ggml_quantize_chunk( - * enum ggml_type type, + * enum ggml_type type, * const float * src, * void * dst, * int64_t start, @@ -726,7 +3328,7 @@ class GGML_quantize_chunk extends MustUse { /** * GGML_API struct gguf_context * gguf_init_empty(void); */ -class GGUF_init_empty extends Alloc { +class GGUF_init_empty extends MustCheck { GGUF_init_empty() { this.getName() = "gguf_init_empty" } @@ -734,11 +3336,11 @@ class GGUF_init_empty extends Alloc { /** * GGML_API struct gguf_context * gguf_init_from_file( - * const char * fname, + * const char * fname, * struct gguf_init_params params * ); */ -class GGUF_init_from_file extends Alloc { +class GGUF_init_from_file extends MustCheck { GGUF_init_from_file() { this.getName() = "gguf_init_from_file" } @@ -747,12 +3349,21 @@ class GGUF_init_from_file extends Alloc { /** * GGML_API void gguf_free(struct gguf_context * ctx); */ -class GGUF_free extends Free { +class GGUF_free extends Function { GGUF_free() { this.getName() = "gguf_free" } } +/** + * GGML_API const char * gguf_type_name(enum gguf_type type); + */ +class GGUF_type_name extends MustCheck { + GGUF_type_name() { + this.getName() = "gguf_type_name" + } +} + /** * GGML_API int gguf_get_version (const struct gguf_context * ctx); */ @@ -780,6 +3391,15 @@ class GGUF_get_data_offset extends MustUse { } } +/** + * GGML_API void * gguf_get_data (const struct gguf_context * ctx); + */ +class GGUF_get_data extends MustCheck { + GGUF_get_data() { + this.getName() = "gguf_get_data" + } +} + /** * GGML_API int gguf_get_n_kv(const struct gguf_context * ctx); */ @@ -801,6 +3421,18 @@ class GGUF_find_key extends MustUse { } } +/** + * GGML_API const char * gguf_get_key ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_key extends MustCheck { + GGUF_get_key() { + this.getName() = "gguf_get_key" + } +} + /** * GGML_API enum gguf_type gguf_get_kv_type ( * const struct gguf_context * ctx, @@ -954,6 +3586,30 @@ class GGUF_get_val_bool extends MustUse { } } +/** + * GGML_API const char * gguf_get_val_str ( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_str extends MustCheck { + GGUF_get_val_str() { + this.getName() = "gguf_get_val_str" + } +} + +/** + * GGML_API const void * gguf_get_val_data( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_val_data extends MustCheck { + GGUF_get_val_data() { + this.getName() = "gguf_get_val_data" + } +} + /** * GGML_API int gguf_get_arr_n (const struct gguf_context * ctx, int key_id); */ @@ -963,6 +3619,31 @@ class GGUF_get_arr_n extends MustUse { } } +/** + * GGML_API const void * gguf_get_arr_data( + * const struct gguf_context * ctx, + * int key_id + * ); + */ +class GGUF_get_arr_data extends MustCheck { + GGUF_get_arr_data() { + this.getName() = "gguf_get_arr_data" + } +} + +/** + * GGML_API const char * gguf_get_arr_str ( + * const struct gguf_context * ctx, + * int key_id, + * int i + * ); + */ +class GGUF_get_arr_str extends MustCheck { + GGUF_get_arr_str() { + this.getName() = "gguf_get_arr_str" + } +} + /** * GGML_API int gguf_get_n_tensors (const struct gguf_context * ctx); */ @@ -996,6 +3677,18 @@ class GGUF_get_tensor_offset extends MustUse { } } +/** + * GGML_API char * gguf_get_tensor_name ( + * const struct gguf_context * ctx, + * int i + * ); + */ +class GGUF_get_tensor_name extends MustCheck { + GGUF_get_tensor_name() { + this.getName() = "gguf_get_tensor_name" + } +} + /** * GGML_API enum ggml_type gguf_get_tensor_type ( * const struct gguf_context * ctx, @@ -1504,44 +4197,3 @@ class GGML_internal_get_type_traits extends MustUse { this.getName() = "ggml_internal_get_type_traits" } } - -// ********************************************************************* -// -// Custom allocators defined by 'ggml.h'. -// -// ********************************************************************* - -/** - * Alloc: - * ggml_init - * - * Free: - * ggml_free - */ -class GGMLContextAllocator extends CustomAllocator { - GGMLContextAllocator() { - this = "GGMLContextAllocator" - } - override predicate isAlloc(Alloc f) { - // TODO: Overload `isAllocatedBy` to check if the `mem_buffer` field is - // not `NULL`. - f instanceof GGML_init - } - - override predicate isFree(Free f) { - f instanceof GGML_free - } -} - -class GGUFContextAllocator extends CustomAllocator { - GGUFContextAllocator() { - this = "GGUFContextAllocator" - } - override predicate isAlloc(Alloc f) { - (f instanceof GGUF_init_empty) or (f instanceof GGUF_init_from_file) - } - - override predicate isFree(Free f) { - f instanceof GGUF_free - } -} \ No newline at end of file diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll index ab4629e..06e8251 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_alloc.qll @@ -1,7 +1,7 @@ // ********************************************************************* // -// This library has been automatically generated using the Busy Work -// VSCode extension from the file 'ggml-alloc.h'. +// This library has been automatically generated using the QLL Writer +// VSCode extension from the the file ggml-alloc.h // // ********************************************************************* import cpp @@ -9,8 +9,8 @@ import trailofbits.common // ********************************************************************* // -// Function types matching the individual functions defined by -// 'ggml-alloc.h'. +// Function types matching the individual functions defined in +// ggml-alloc.h // // ********************************************************************* @@ -79,7 +79,7 @@ class GGML_gallocr_reserve extends MustUse { /** * GGML_API bool ggml_gallocr_reserve_n( - * ggml_gallocr_t galloc, + * ggml_gallocr_t galloc, * struct ggml_cgraph * graph, * const int * node_buffer_ids, * const int * leaf_buffer_ids @@ -115,21 +115,48 @@ class GGML_gallocr_get_buffer_size extends MustUse { } } +/** + * GGML_API struct ggml_backend_buffer * ggml_backend_alloc_ctx_tensors_from_buft( + * struct ggml_context * ctx, + * ggml_backend_buffer_type_t buft + * ); + */ +class GGML_backend_alloc_ctx_tensors_from_buft extends MustCheck { + GGML_backend_alloc_ctx_tensors_from_buft() { + this.getName() = "ggml_backend_alloc_ctx_tensors_from_buft" + } +} + +/** + * GGML_API struct ggml_backend_buffer * ggml_backend_alloc_ctx_tensors( + * struct ggml_context * ctx, + * ggml_backend_t backend + * ); + */ +class GGML_backend_alloc_ctx_tensors extends MustCheck { + GGML_backend_alloc_ctx_tensors() { + this.getName() = "ggml_backend_alloc_ctx_tensors" + } +} + // ********************************************************************* // -// Custom allocators defined by 'ggml-alloc.h'. +// Custom allocators defined in ggml-alloc.h // // ********************************************************************* /** - * Alloc: - * ggml_gallocr_new + * GGML_gallocr_allocator + * + * Allocation functions: + * - ggml_gallocr_new + * - ggml_gallocr_new_n * - * Free: - * ggml_gallocr_new + * Deallocation functions: + * - ggml_gallocr_free */ -class GGMLGraphAllocator extends CustomAllocator { - GGMLGraphAllocator() { this = "GGMLGraphAllocator" } +class GGML_gallocr_allocator extends CustomAllocator { + GGML_gallocr_allocator() { this = "GGML_gallocr_allocator" } override predicate isAlloc(Alloc f) { (f instanceof GGML_gallocr_new) or (f instanceof GGML_gallocr_new_n) diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll index 2112fea..c44dfab 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll @@ -1,7 +1,7 @@ // ********************************************************************* // -// This library has been automatically generated using the Busy Work -// VSCode extension from the file 'ggml-backend.h'. +// This library has been automatically generated using the QLL Writer +// VSCode extension from the the file ggml-backend.h // // ********************************************************************* import cpp @@ -9,11 +9,22 @@ import trailofbits.common // ********************************************************************* // -// Function types matching the individual functions defined by -// 'ggml-backend.h'. +// Function types matching the individual functions defined in +// ggml-backend.h // // ********************************************************************* +/** + * GGML_API const char * ggml_backend_buft_name ( + * ggml_backend_buffer_type_t buft + * ); + */ +class GGML_backend_buft_name extends MustCheck { + GGML_backend_buft_name() { + this.getName() = "ggml_backend_buft_name" + } +} + /** * GGML_API GGML_CALL ggml_backend_buffer_t ggml_backend_buft_alloc_buffer ( * ggml_backend_buffer_type_t buft, @@ -81,6 +92,17 @@ class GGML_backend_buft_is_host extends MustUse { } } +/** + * GGML_API const char * ggml_backend_buffer_name ( + * ggml_backend_buffer_t buffer + * ); + */ +class GGML_backend_buffer_name extends MustCheck { + GGML_backend_buffer_name() { + this.getName() = "ggml_backend_buffer_name" + } +} + /** * GGML_API void ggml_backend_buffer_free (ggml_backend_buffer_t buffer); */ @@ -90,6 +112,15 @@ class GGML_backend_buffer_free extends Function { } } +/** + * GGML_API void * ggml_backend_buffer_get_base (ggml_backend_buffer_t buffer); + */ +class GGML_backend_buffer_get_base extends MustCheck { + GGML_backend_buffer_get_base() { + this.getName() = "ggml_backend_buffer_get_base" + } +} + /** * GGML_API size_t ggml_backend_buffer_get_size (ggml_backend_buffer_t buffer); */ @@ -207,6 +238,15 @@ class GGML_backend_guid extends MustUse { } } +/** + * GGML_API const char * ggml_backend_name(ggml_backend_t backend); + */ +class GGML_backend_name extends MustCheck { + GGML_backend_name() { + this.getName() = "ggml_backend_name" + } +} + /** * GGML_API void ggml_backend_free(ggml_backend_t backend); */ @@ -289,7 +329,7 @@ class GGML_backend_tensor_get_async extends Function { /** * GGML_API GGML_CALL void ggml_backend_tensor_set( - * struct ggml_tensor * tensor, + * struct ggml_tensor * tensor, * const void * data, * size_t offset, * size_t size @@ -588,6 +628,15 @@ class GGML_backend_reg_init_backend_from_str extends MustUse { } } +/** + * GGML_API const char * ggml_backend_reg_get_name(size_t i); + */ +class GGML_backend_reg_get_name extends MustCheck { + GGML_backend_reg_get_name() { + this.getName() = "ggml_backend_reg_get_name" + } +} + /** * GGML_API ggml_backend_t ggml_backend_reg_init_backend( * size_t i, @@ -846,19 +895,21 @@ class GGML_backend_view_init extends Function { // ********************************************************************* // -// Custom allocators defined by 'ggml-backend.h'. +// Custom allocators defined in ggml-backend.h // // ********************************************************************* /** - * Alloc: - * ggml_backend_event_new + * GGML_backend_event_allocator * - * Free: - * ggml_backend_event_free + * Allocation functions: + * - ggml_backend_event_new + * + * Deallocation functions: + * - ggml_backend_event_free */ -class GGMLBackendEventAllocator extends CustomAllocator { - GGMLBackendEventAllocator() { this = "GGMLBackendEventAllocator" } +class GGML_backend_event_allocator extends CustomAllocator { + GGML_backend_event_allocator() { this = "GGML_backend_event_allocator" } override predicate isAlloc(Alloc f) { f instanceof GGML_backend_event_new @@ -870,14 +921,16 @@ class GGMLBackendEventAllocator extends CustomAllocator { } /** - * Alloc: - * ggml_backend_sched_new + * GGML_backend_sched_allocator + * + * Allocation functions: + * - ggml_backend_sched_new * - * Free: - * ggml_backend_sched_free + * Deallocation functions: + * - ggml_backend_sched_free */ -class GGMLBackendScheduleAllocator extends CustomAllocator { - GGMLBackendScheduleAllocator() { this = "GGMLBackendScheduleAllocator" } +class GGML_backend_sched_allocator extends CustomAllocator { + GGML_backend_sched_allocator() { this = "GGML_backend_sched_allocator" } override predicate isAlloc(Alloc f) { f instanceof GGML_backend_sched_new From 3a25608209c1be422924b34b98f8869fc9b47929 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Thu, 27 Jun 2024 12:53:17 +0200 Subject: [PATCH 17/19] Added Depracated to trailofbits.common --- cpp/lib/trailofbits/common/ReturnValue.qll | 5 +++++ cpp/src/ml/UseOfDeprecatedFunction.ql | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 cpp/src/ml/UseOfDeprecatedFunction.ql diff --git a/cpp/lib/trailofbits/common/ReturnValue.qll b/cpp/lib/trailofbits/common/ReturnValue.qll index 9ecce24..30d6852 100644 --- a/cpp/lib/trailofbits/common/ReturnValue.qll +++ b/cpp/lib/trailofbits/common/ReturnValue.qll @@ -2,6 +2,11 @@ import cpp import semmle.code.cpp.dataflow.new.DataFlow +/** + * Identifies deprecated functions that should not be used. + */ +abstract class Deprecated extends Function { } + /** * Identifies functions where the return value must be used in some way. */ diff --git a/cpp/src/ml/UseOfDeprecatedFunction.ql b/cpp/src/ml/UseOfDeprecatedFunction.ql new file mode 100644 index 0000000..4d68707 --- /dev/null +++ b/cpp/src/ml/UseOfDeprecatedFunction.ql @@ -0,0 +1,19 @@ +/** + * @name Use of deprecated function + * @id tob/cpp/ggml-deprecated-function-use + * @description The called function is deprecated and should not be used + * @kind problem + * @tags ml + * @problem.severity warning + * @precision high + * @group ml + */ + +import cpp +import trailofbits.common +import trailofbits.ml.libraries + +from + Deprecated deprecated +select + deprecated.getACallToThisFunction(), "This function is deprecated and should not be used" From e56adb1dfa3947c225faa20dbcb3ba3847db9e15 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Thu, 27 Jun 2024 12:53:42 +0200 Subject: [PATCH 18/19] Tweaked descriptions --- cpp/src/ml/LocalMemoryLeak.ql | 2 +- cpp/src/ml/LocalUseAfterFree.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/ml/LocalMemoryLeak.ql b/cpp/src/ml/LocalMemoryLeak.ql index 8589354..e309bb5 100644 --- a/cpp/src/ml/LocalMemoryLeak.ql +++ b/cpp/src/ml/LocalMemoryLeak.ql @@ -1,7 +1,7 @@ /** * @name Memory leak from a GGML custom allocator * @id tob/cpp/ggml-memory-leak - * @description A value allocated using a GGML custom allocator is never freed, leaking the corresponding memory + * @description A value allocated using a custom allocator is never freed, leaking the corresponding memory * @kind problem * @tags correctness ml * @problem.severity warning diff --git a/cpp/src/ml/LocalUseAfterFree.ql b/cpp/src/ml/LocalUseAfterFree.ql index 934fc62..e5c455d 100644 --- a/cpp/src/ml/LocalUseAfterFree.ql +++ b/cpp/src/ml/LocalUseAfterFree.ql @@ -1,7 +1,7 @@ /** * @name Use after free using a GGML custom allocator * @id tob/cpp/ggml-use-after-free - * @description A value allocated using a GGML custom allocator is freed, and then reused without being reallocated. + * @description A value allocated using a custom allocator is freed, and then reused without being reallocated. * @kind problem * @tags correctness ml * @problem.severity warning From 94998a387fb09e8a8eeeebe13f7a0a991b40c3c7 Mon Sep 17 00:00:00 2001 From: Fredrik Dahlgren Date: Thu, 27 Jun 2024 15:04:44 +0200 Subject: [PATCH 19/19] Updated auto-generated QL libraries for GGML header files --- cpp/lib/trailofbits/ml/ggml/ggml.qll | 31 +++++++- cpp/lib/trailofbits/ml/ggml/ggml_backend.qll | 77 ++++++++++++++++++-- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/cpp/lib/trailofbits/ml/ggml/ggml.qll b/cpp/lib/trailofbits/ml/ggml/ggml.qll index 1e88d47..a77da90 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml.qll @@ -425,7 +425,7 @@ class GGML_tensor_overhead extends MustUse { /** * GGML_API struct ggml_context * ggml_init(struct ggml_init_params params); */ -class GGML_init extends MustCheck { +class GGML_init extends Alloc { GGML_init() { this.getName() = "ggml_init" } @@ -434,7 +434,7 @@ class GGML_init extends MustCheck { /** * GGML_API void ggml_free(struct ggml_context * ctx); */ -class GGML_free extends Function { +class GGML_free extends Free { GGML_free() { this.getName() = "ggml_free" } @@ -4197,3 +4197,30 @@ class GGML_internal_get_type_traits extends MustUse { this.getName() = "ggml_internal_get_type_traits" } } + +// ********************************************************************* +// +// Custom allocators defined in ggml.h +// +// ********************************************************************* + +/** + * GGML_allocator + * + * Allocation functions: + * - ggml_init + * + * Deallocation functions: + * - ggml_free + */ +class GGML_allocator extends CustomAllocator { + GGML_allocator() { this = "GGML_allocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_init + } + + override predicate isFree(Free f) { + f instanceof GGML_free + } +} diff --git a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll index c44dfab..8ef55b5 100644 --- a/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll +++ b/cpp/lib/trailofbits/ml/ggml/ggml_backend.qll @@ -31,7 +31,7 @@ class GGML_backend_buft_name extends MustCheck { * size_t size * ); */ -class GGML_backend_buft_alloc_buffer extends MustUse { +class GGML_backend_buft_alloc_buffer extends Function { GGML_backend_buft_alloc_buffer() { this.getName() = "ggml_backend_buft_alloc_buffer" } @@ -106,7 +106,7 @@ class GGML_backend_buffer_name extends MustCheck { /** * GGML_API void ggml_backend_buffer_free (ggml_backend_buffer_t buffer); */ -class GGML_backend_buffer_free extends Function { +class GGML_backend_buffer_free extends Free { GGML_backend_buffer_free() { this.getName() = "ggml_backend_buffer_free" } @@ -250,7 +250,7 @@ class GGML_backend_name extends MustCheck { /** * GGML_API void ggml_backend_free(ggml_backend_t backend); */ -class GGML_backend_free extends Function { +class GGML_backend_free extends Free { GGML_backend_free() { this.getName() = "ggml_backend_free" } @@ -273,7 +273,7 @@ class GGML_backend_get_default_buffer_type extends MustUse { * size_t size * ); */ -class GGML_backend_alloc_buffer extends MustUse { +class GGML_backend_alloc_buffer extends Alloc { GGML_backend_alloc_buffer() { this.getName() = "ggml_backend_alloc_buffer" } @@ -527,7 +527,7 @@ class GGML_backend_event_wait extends Function { /** * GGML_API ggml_backend_t ggml_backend_cpu_init(void); */ -class GGML_backend_cpu_init extends MustUse { +class GGML_backend_cpu_init extends Alloc { GGML_backend_cpu_init() { this.getName() = "ggml_backend_cpu_init" } @@ -836,7 +836,7 @@ class GGML_backend_sched_set_eval_callback extends Function { * struct ggml_cgraph * graph * ); */ -class GGML_backend_graph_copy extends MustUse { +class GGML_backend_graph_copy extends Alloc { GGML_backend_graph_copy() { this.getName() = "ggml_backend_graph_copy" } @@ -847,7 +847,7 @@ class GGML_backend_graph_copy extends MustUse { * struct ggml_backend_graph_copy copy * ); */ -class GGML_backend_graph_copy_free extends Function { +class GGML_backend_graph_copy_free extends Free { GGML_backend_graph_copy_free() { this.getName() = "ggml_backend_graph_copy_free" } @@ -940,3 +940,66 @@ class GGML_backend_sched_allocator extends CustomAllocator { f instanceof GGML_backend_sched_free } } + +/** + * GGML_backend_graph_copy_allocator + * + * Allocation functions: + * - ggml_backend_graph_copy + * + * Deallocation functions: + * - ggml_backend_graph_copy_free + */ +class GGML_backend_graph_copy_allocator extends CustomAllocator { + GGML_backend_graph_copy_allocator() { this = "GGML_backend_graph_copy_allocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_graph_copy + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_graph_copy_free + } +} + +/** + * GGML_backend_buffer_allocator + * + * Allocation functions: + * - ggml_backend_alloc_buffer + * + * Deallocation functions: + * - ggml_backend_buffer_free + */ +class GGML_backend_buffer_allocator extends CustomAllocator { + GGML_backend_buffer_allocator() { this = "GGML_backend_buffer_allocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_alloc_buffer + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_buffer_free + } +} + +/** + * GGML_backend_allocator + * + * Allocation functions: + * - ggml_backend_cpu_init + * + * Deallocation functions: + * - ggml_backend_free + */ +class GGML_backend_allocator extends CustomAllocator { + GGML_backend_allocator() { this = "GGML_backend_allocator" } + + override predicate isAlloc(Alloc f) { + f instanceof GGML_backend_cpu_init + } + + override predicate isFree(Free f) { + f instanceof GGML_backend_free + } +}