@@ -192,6 +192,37 @@ private class UnsignedMulExpr extends MulExpr {
192
192
}
193
193
}
194
194
195
+ /**
196
+ * Gets the value of the `EOF` macro.
197
+ *
198
+ * This is typically `"-1"`, but this is not guaranteed to be the case on all
199
+ * systems.
200
+ */
201
+ private int getEofValue ( ) {
202
+ exists ( MacroInvocation mi |
203
+ mi .getMacroName ( ) = "EOF" and
204
+ result = unique( | | mi .getExpr ( ) .getValue ( ) .toInt ( ) )
205
+ )
206
+ }
207
+
208
+ /** Get standard `getc` function or related variants. */
209
+ private class Getc extends Function {
210
+ Getc ( ) { this .hasGlobalOrStdOrBslName ( [ "fgetc" , "getc" ] ) }
211
+ }
212
+
213
+ /** A call to `getc` */
214
+ private class CallToGetc extends FunctionCall {
215
+ CallToGetc ( ) { this .getTarget ( ) instanceof Getc }
216
+ }
217
+
218
+ /**
219
+ * A call to `getc` that we can analyze because we know
220
+ * the value of the `EOF` macro.
221
+ */
222
+ private class AnalyzableCallToGetc extends CallToGetc {
223
+ AnalyzableCallToGetc ( ) { exists ( getEofValue ( ) ) }
224
+ }
225
+
195
226
/**
196
227
* Holds if `expr` is effectively a multiplication of `operand` with the
197
228
* positive constant `positive`.
@@ -287,6 +318,8 @@ private predicate analyzableExpr(Expr e) {
287
318
or
288
319
e instanceof RemExpr
289
320
or
321
+ e instanceof AnalyzableCallToGetc
322
+ or
290
323
// A conversion is analyzable, provided that its child has an arithmetic
291
324
// type. (Sometimes the child is a reference type, and so does not get
292
325
// any bounds.) Rather than checking whether the type of the child is
@@ -861,6 +894,14 @@ private float getLowerBoundsImpl(Expr expr) {
861
894
)
862
895
)
863
896
or
897
+ exists ( AnalyzableCallToGetc getc |
898
+ expr = getc and
899
+ // from https://en.cppreference.com/w/c/io/fgetc:
900
+ // On success, returns the obtained character as an unsigned char
901
+ // converted to an int. On failure, returns EOF.
902
+ result = min ( [ typeLowerBound ( any ( UnsignedCharType pct ) ) , getEofValue ( ) ] )
903
+ )
904
+ or
864
905
// If the conversion is to an arithmetic type then we just return the
865
906
// lower bound of the child. We do not need to handle truncation and
866
907
// overflow here, because that is done in `getTruncatedLowerBounds`.
@@ -1055,6 +1096,14 @@ private float getUpperBoundsImpl(Expr expr) {
1055
1096
)
1056
1097
)
1057
1098
or
1099
+ exists ( AnalyzableCallToGetc getc |
1100
+ expr = getc and
1101
+ // from https://en.cppreference.com/w/c/io/fgetc:
1102
+ // On success, returns the obtained character as an unsigned char
1103
+ // converted to an int. On failure, returns EOF.
1104
+ result = max ( [ typeUpperBound ( any ( UnsignedCharType pct ) ) , getEofValue ( ) ] )
1105
+ )
1106
+ or
1058
1107
// If the conversion is to an arithmetic type then we just return the
1059
1108
// upper bound of the child. We do not need to handle truncation and
1060
1109
// overflow here, because that is done in `getTruncatedUpperBounds`.
0 commit comments