Skip to content
This repository was archived by the owner on Nov 19, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ node_modules
# Generated via `codeql-mcp-server-ci` actions workflow
models-output.json

# Test databases created via `codeql test run`
# Test databases and artifacts created via `codeql test run`
*.testproj
*.actual
*.bqrs
trap

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Allocating memory with a size controlled by an external user can result in integer overflow or
excessive memory consumption, leading to denial of service (DoS) attacks.
</p>

</overview>
<recommendation>

<p>
Ensure that allocation sizes are properly validated and restricted to reasonable limits before
allocating memory. Consider using a maximum size constant or validating the size against known
safe bounds.
</p>

</recommendation>
<example>

<p>
In the following example, the allocation size is directly controlled by user input without
validation:
</p>

<sample src="UncontrolledAllocationSizeBad.go" />

<p>
In the corrected example, the allocation size is validated against a maximum value before
allocating:
</p>

<sample src="UncontrolledAllocationSizeGood.go" />

</example>
<references>

<li>
OWASP:
<a href="https://owasp.org/www-community/vulnerabilities/Denial_of_Service">Denial of Service</a>.
</li>
<li>
CWE:
<a href="https://cwe.mitre.org/data/definitions/770.html">CWE-770: Allocation of Resources Without Limits or Throttling</a>.
</li>

</references>
</qhelp>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @name Uncontrolled allocation size
* @description Allocating memory with a size controlled by an external user can result in integer
* overflow or denial of service (DoS).
* @kind path-problem
* @problem.severity warning
* @security-severity 7.5
* @precision high
* @id go/uncontrolled-allocation-size
* @tags security
* external/cwe/cwe-770
*/

import go
import semmle.go.dataflow.DataFlow
import semmle.go.dataflow.TaintTracking

/**
* A data flow configuration for tracking user-controlled values that flow to allocation size arguments.
*/
module UncontrolledAllocationSizeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

predicate isSink(DataFlow::Node sink) {
exists(CallExpr call |
call.getTarget().getName() = "make" and
sink.asExpr() = call.getArgument(1)
)
}
}

module UncontrolledAllocationSizeFlow = TaintTracking::Global<UncontrolledAllocationSizeConfig>;

import UncontrolledAllocationSizeFlow::PathGraph

from UncontrolledAllocationSizeFlow::PathNode source, UncontrolledAllocationSizeFlow::PathNode sink
where UncontrolledAllocationSizeFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This memory allocation depends on a $@.",
source.getNode(), "user-provided value"
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
edges
| UncontrolledAllocationSizeBad.go:11:12:11:16 | selection of URL | UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
| UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | UncontrolledAllocationSizeBad.go:13:15:13:20 | source | provenance | |
| UncontrolledAllocationSizeBad.go:13:15:13:20 | source | UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | provenance | MaD:3 |
| UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | provenance | |
| UncontrolledAllocationSizeBad.go:14:2:14:37 | ... := ...[0] | UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | provenance | |
| UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | UncontrolledAllocationSizeBad.go:14:2:14:37 | ... := ...[0] | provenance | Config |
nodes
| UncontrolledAllocationSizeBad.go:11:12:11:16 | selection of URL | semmle.label | selection of URL |
| UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | semmle.label | call to Query |
| UncontrolledAllocationSizeBad.go:13:15:13:20 | source | semmle.label | source |
| UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | semmle.label | call to Get |
| UncontrolledAllocationSizeBad.go:14:2:14:37 | ... := ...[0] | semmle.label | ... := ...[0] |
| UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | semmle.label | sourceStr |
| UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | semmle.label | sink |
subpaths
#select
| UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | UncontrolledAllocationSizeBad.go:11:12:11:16 | selection of URL | UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | This memory allocation depends on a $@. | UncontrolledAllocationSizeBad.go:11:12:11:16 | selection of URL | user-provided value |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UncontrolledAllocationSize/UncontrolledAllocationSize.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
)

func OutOfMemoryBad(w http.ResponseWriter, r *http.Request) {
source := r.URL.Query()
// Get user-controlled input
sourceStr := source.Get("size")
sink, err := strconv.Atoi(sourceStr)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// BAD: Uncontrolled allocation size from user input
result := make([]string, sink)
for i := 0; i < sink; i++ {
result[i] = fmt.Sprintf("Item %d", i+1)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(result)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
)

func OutOfMemoryGood(w http.ResponseWriter, r *http.Request) {
source := r.URL.Query()
MaxValue := 100
// Get user-controlled input
sourceStr := source.Get("size")
sink, err := strconv.Atoi(sourceStr)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// GOOD: Validate the size before allocation
if sink < 0 || sink > MaxValue {
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
result := make([]string, sink)
for i := 0; i < sink; i++ {
result[i] = fmt.Sprintf("Item %d", i+1)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(result)
}
3 changes: 3 additions & 0 deletions languages/go/custom/test/UncontrolledAllocationSize/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module test

go 1.21