divide by zero rule

This commit is contained in:
Your Name
2021-01-03 00:51:34 +03:00
parent ace9271cc4
commit 4b36a62834
3 changed files with 99 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Divide by zero is division where the divisor (denominator) is zero.
In Golang language, integer divide by zero leads to panic(), which might interrupt execution of the program and lead to program termination.
</p>
</overview>
<recommendation>
<p>
Every user input should be checked for correctness, if needed.
In case of divide by zero, comparison with zero should be added. It is also possible to handle panic(),
generated by division by zero, by built-in function recover().
</p>
</recommendation>
<example>
<p>
The following example shows simplified case, when data received from user input, which is used as a divisor and
causes divide by zero with panic signal.
</p>
<sample src="DivideByZeroBad.go" />
</example>
</qhelp>

View File

@@ -0,0 +1,57 @@
/**
* @name Divide by zero
* @description Converting the result of `strconv.Atoi`, `strconv.ParseInt`,
* and `strconv.ParseUint` to integer types or use of integer types for division without checks
* might lead to division by zero and panic, which cause denial of service.
* @kind path-problem
* @problem.severity error
* @id go/divide-by-zero
* @tags security
* external/cwe/cwe-369
*/
import go
import DataFlow::PathGraph
class DivideByZeroSanitizeGuard extends DataFlow::BarrierGuard, DataFlow::EqualityTestNode {
override predicate checks(Expr e, boolean branch) {
exists(DataFlow::Node zero, DataFlow::Node sink |
zero.getNumericValue() = 0 and
sink.getType().getUnderlyingType() instanceof SignedIntegerType and
this.eq(branch.booleanNot(), sink, zero) and
globalValueNumber(DataFlow::exprNode(e)) = globalValueNumber(sink)
)
}
}
class DivideByZeroCheckConfig extends TaintTracking::Configuration {
DivideByZeroCheckConfig() { this = "DivideByZeroCheckConfig" }
override predicate isSource(DataFlow::Node source) {
exists(DataFlow::CallNode c, IntegerParser::Range ip |
c.getTarget() = ip and source = c.getResult(0)
)
or
exists(IntegerType integerType | source.getType().getUnderlyingType() = integerType)
}
override predicate isSink(DataFlow::Node sink) {
exists(IntegerType integerType, QuoExpr e |
sink.asExpr().getParent().(QuoExpr).getRightOperand() = e.getAnOperand() and
not sink.asExpr().getParent().(QuoExpr).getRightOperand().isConst() and
sink.getType().getUnderlyingType() = integerType
)
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof DivideByZeroSanitizeGuard
}
}
from
DataFlow::PathNode source, DataFlow::PathNode sink, DivideByZeroCheckConfig cfg,
DataFlow::CallNode call
where cfg.hasFlowPath(source, sink) and call.getResult(0) = source.getNode()
select sink, source, sink,
"Variable $@, which is used at division statement might be zero and leads to division by zero exception.",
sink, sink.getNode().toString()

View File

@@ -0,0 +1,19 @@
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) < 2 {
fmt.Printf("Usage: ./program value\n")
return
}
val1 := 1337
value, _ := strconv.Atoi(os.Args[1])
out := val1 / value
fmt.Println(out)
return
}