|
3 | 3 | * @name RULE-1-5: Disallowed obsolescent usage of 'ungetc' on a file stream at position zero |
4 | 4 | * @description Calling the function 'ungetc' on a file stream with a position of zero is an |
5 | 5 | * obsolescent language feature. |
6 | | - * @kind problem |
| 6 | + * @kind path-problem |
7 | 7 | * @precision medium |
8 | 8 | * @problem.severity error |
9 | 9 | * @tags external/misra/id/rule-1-5 |
@@ -52,18 +52,30 @@ class MoveStreamPositionCall extends FunctionCall { |
52 | 52 | Expr getStreamArgument() { result = streamArgument } |
53 | 53 | } |
54 | 54 |
|
55 | | -from FunctionCall ungetc, DataFlow::Node file |
| 55 | +module FilePositionZeroFlowConfig implements DataFlow::ConfigSig { |
| 56 | + predicate isSource(DataFlow::Node node) { |
| 57 | + node.asIndirectExpr().(FunctionCall).getTarget().hasGlobalOrStdName("fopen") |
| 58 | + } |
| 59 | + |
| 60 | + predicate isSink(DataFlow::Node node) { |
| 61 | + exists(FunctionCall fc | |
| 62 | + fc.getTarget().hasGlobalOrStdName("ungetc") and |
| 63 | + node.asIndirectExpr() = fc.getArgument(1) |
| 64 | + ) |
| 65 | + } |
| 66 | + |
| 67 | + predicate isBarrierIn(DataFlow::Node node) { |
| 68 | + exists(MoveStreamPositionCall fc | node.asIndirectExpr() = fc.getStreamArgument()) |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +module FilePositionZeroFlow = DataFlow::Global<FilePositionZeroFlowConfig>; |
| 73 | + |
| 74 | +import FilePositionZeroFlow::PathGraph |
| 75 | + |
| 76 | +from FilePositionZeroFlow::PathNode sink, FilePositionZeroFlow::PathNode source |
56 | 77 | where |
57 | | - not isExcluded(ungetc, Language4Package::ungetcCallOnStreamPositionZeroQuery()) and |
58 | | - // ungetc() called on file stream |
59 | | - ungetc.getTarget().hasGlobalOrStdName("ungetc") and |
60 | | - DataFlow::localFlow(file, DataFlow::exprNode(ungetc.getArgument(1))) and |
61 | | - // ungetc() is not dominated by a fread() etc to that file stream |
62 | | - not exists(MoveStreamPositionCall moveStreamCall | |
63 | | - DataFlow::localFlow(file, DataFlow::exprNode(moveStreamCall.getStreamArgument())) and |
64 | | - dominates(moveStreamCall, ungetc) |
65 | | - ) |
66 | | - // the file stream is the root of the local data flow |
67 | | - and not DataFlow::localFlow(any(DataFlow::Node n | not n = file), file) |
68 | | -select ungetc, "Obsolescent call to ungetc on file stream $@ at position zero.", file, |
69 | | - file.toString() |
| 78 | + not isExcluded(sink.getNode().asExpr(), Language4Package::ungetcCallOnStreamPositionZeroQuery()) and |
| 79 | + FilePositionZeroFlow::flowPath(source, sink) |
| 80 | +select sink.getNode(), source, sink, |
| 81 | + "Obsolescent call to ungetc on file stream $@ at position zero.", source, source.toString() |
0 commit comments