--- /dev/null
+/**
+ * @name Invalid use of chunk_from_chars() macro
+ * @description The chunk_from_chars() macro creates a temporary chunk_t, which
+ * is not defined outside of the block in which it has been used,
+ * therefore, compilers might optimize out the assignment.
+ * @kind path-problem
+ * @problem.severity error
+ * @id strongswan/invalid-chunk-from-chars
+ * @tags correctness
+ * @precision very-high
+ */
+import cpp
+import DataFlow::PathGraph
+import semmle.code.cpp.dataflow.DataFlow
+
+class ChunkFromChars extends Expr {
+ ChunkFromChars() {
+ this = any(MacroInvocation mi |
+ mi.getOutermostMacroAccess().getMacroName() = "chunk_from_chars"
+ /* ignore global static uses of the macro */
+ and exists (Block b | mi.getExpr().getEnclosingBlock() = b)
+ ).getExpr()
+ }
+}
+
+class ChunkFromCharsUsage extends DataFlow::Configuration {
+ ChunkFromCharsUsage() { this = "ChunkFromCharsUsage" }
+
+ override predicate isSource(DataFlow::Node source) {
+ source.asExpr() instanceof ChunkFromChars
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(sink.asExpr())
+ }
+
+ override predicate isBarrierOut(DataFlow::Node node) {
+ /* don't track beyond function calls */
+ exists(FunctionCall fc | node.asExpr().getParent*() = fc)
+ }
+}
+
+Block enclosingBlock(Block b) {
+ result = b.getEnclosingBlock()
+}
+
+from ChunkFromCharsUsage usage, DataFlow::PathNode source, DataFlow::PathNode sink
+where
+ usage.hasFlowPath(source, sink)
+ and not source.getNode().asExpr().getEnclosingBlock() = enclosingBlock*(sink.getNode().asExpr().getEnclosingBlock())
+select source, source, sink, "Invalid use of chunk_from_chars() result in sibling/parent block."