@@ -205,57 +205,104 @@ private predicate deconstructSizeExpr(Expr sizeExpr, Expr lengthExpr, int sizeof
205205 sizeof = 1
206206}
207207
208- /**
209- * An allocation expression that is a function call, such as call to `malloc`.
210- */
211- private class CallAllocationExpr extends AllocationExpr , FunctionCall {
212- AllocationFunction target ;
213-
214- CallAllocationExpr ( ) {
215- target = this .getTarget ( ) and
216- // realloc(ptr, 0) only frees the pointer
217- not (
218- exists ( target .getReallocPtrArg ( ) ) and
219- this .getArgument ( target .getSizeArg ( ) ) .getValue ( ) .toInt ( ) = 0
220- ) and
221- // these are modeled directly (and more accurately), avoid duplication
222- not exists ( NewOrNewArrayExpr new | new .getAllocatorCall ( ) = this )
223- }
224-
225- override Expr getSizeExpr ( ) {
226- exists ( Expr sizeExpr | sizeExpr = this .getArgument ( target .getSizeArg ( ) ) |
227- if exists ( target .getSizeMult ( ) )
228- then result = sizeExpr
229- else
230- exists ( Expr lengthExpr |
231- deconstructSizeExpr ( sizeExpr , lengthExpr , _) and
232- result = lengthExpr
208+ private signature class CallAllocationExprTarget extends Function ;
209+
210+ private module CallAllocationExprBase< CallAllocationExprTarget Target> {
211+ signature int getReallocPtrArgSig ( Target target ) ;
212+
213+ signature int getSizeArgSig ( Target target ) ;
214+
215+ signature int getSizeMultSig ( Target target ) ;
216+
217+ signature predicate requiresDeallocSig ( Target target ) ;
218+
219+ module With<
220+ getReallocPtrArgSig / 1 getReallocPtrArg, getSizeArgSig / 1 getSizeArg, getSizeMultSig / 1 getSizeMult,
221+ requiresDeallocSig / 1 requiresDealloc> {
222+ /**
223+ * An allocation expression that is a function call, such as call to `malloc`.
224+ */
225+ class CallAllocationExprImpl instanceof FunctionCall {
226+ Target target ;
227+
228+ CallAllocationExprImpl ( ) {
229+ target = this .getTarget ( ) and
230+ // realloc(ptr, 0) only frees the pointer
231+ not (
232+ exists ( getReallocPtrArg ( target ) ) and
233+ this .getArgument ( getSizeArg ( target ) ) .getValue ( ) .toInt ( ) = 0
234+ ) and
235+ // these are modeled directly (and more accurately), avoid duplication
236+ not exists ( NewOrNewArrayExpr new | new .getAllocatorCall ( ) = this )
237+ }
238+
239+ string toString ( ) { result = super .toString ( ) }
240+
241+ Expr getSizeExprImpl ( ) {
242+ exists ( Expr sizeExpr | sizeExpr = super .getArgument ( getSizeArg ( target ) ) |
243+ if exists ( getSizeMult ( target ) )
244+ then result = sizeExpr
245+ else
246+ exists ( Expr lengthExpr |
247+ deconstructSizeExpr ( sizeExpr , lengthExpr , _) and
248+ result = lengthExpr
249+ )
233250 )
234- )
251+ }
252+
253+ int getSizeMultImpl ( ) {
254+ // malloc with multiplier argument that is a constant
255+ result = super .getArgument ( getSizeMult ( target ) ) .getValue ( ) .toInt ( )
256+ or
257+ // malloc with no multiplier argument
258+ not exists ( getSizeMult ( target ) ) and
259+ deconstructSizeExpr ( super .getArgument ( getSizeArg ( target ) ) , _, result )
260+ }
261+
262+ int getSizeBytesImpl ( ) {
263+ result = this .getSizeExprImpl ( ) .getValue ( ) .toInt ( ) * this .getSizeMultImpl ( )
264+ }
265+
266+ Expr getReallocPtrImpl ( ) { result = super .getArgument ( getReallocPtrArg ( target ) ) }
267+
268+ Type getAllocatedElementTypeImpl ( ) {
269+ result =
270+ super .getFullyConverted ( ) .getType ( ) .stripTopLevelSpecifiers ( ) .( PointerType ) .getBaseType ( ) and
271+ not result instanceof VoidType
272+ }
273+
274+ predicate requiresDeallocImpl ( ) { requiresDealloc ( target ) }
275+ }
235276 }
277+ }
236278
237- override int getSizeMult ( ) {
238- // malloc with multiplier argument that is a constant
239- result = this .getArgument ( target .getSizeMult ( ) ) .getValue ( ) .toInt ( )
240- or
241- // malloc with no multiplier argument
242- not exists ( target .getSizeMult ( ) ) and
243- deconstructSizeExpr ( this .getArgument ( target .getSizeArg ( ) ) , _, result )
244- }
279+ private module CallAllocationExpr {
280+ private int getReallocPtrArg ( AllocationFunction f ) { result = f .getReallocPtrArg ( ) }
245281
246- override int getSizeBytes ( ) {
247- result = this .getSizeExpr ( ) .getValue ( ) .toInt ( ) * this .getSizeMult ( )
248- }
282+ private int getSizeArg ( AllocationFunction f ) { result = f .getSizeArg ( ) }
249283
250- override Expr getReallocPtr ( ) { result = this . getArgument ( target . getReallocPtrArg ( ) ) }
284+ private int getSizeMult ( AllocationFunction f ) { result = f . getSizeMult ( ) }
251285
252- override Type getAllocatedElementType ( ) {
253- result =
254- this .getFullyConverted ( ) .getType ( ) .stripTopLevelSpecifiers ( ) .( PointerType ) .getBaseType ( ) and
255- not result instanceof VoidType
256- }
286+ private predicate requiresDealloc ( AllocationFunction f ) { f .requiresDealloc ( ) }
287+
288+ private class Base =
289+ CallAllocationExprBase< AllocationFunction > :: With< getReallocPtrArg / 1 , getSizeArg / 1 , getSizeMult / 1 , requiresDealloc / 1 > :: CallAllocationExprImpl ;
290+
291+ class CallAllocationExpr extends AllocationExpr , Base {
292+ override Expr getSizeExpr ( ) { result = super .getSizeExprImpl ( ) }
293+
294+ override int getSizeMult ( ) { result = super .getSizeMultImpl ( ) }
257295
258- override predicate requiresDealloc ( ) { target .requiresDealloc ( ) }
296+ override Type getAllocatedElementType ( ) { result = super .getAllocatedElementTypeImpl ( ) }
297+
298+ override predicate requiresDealloc ( ) { super .requiresDeallocImpl ( ) }
299+
300+ override int getSizeBytes ( ) { result = super .getSizeBytesImpl ( ) }
301+
302+ override Expr getReallocPtr ( ) { result = super .getReallocPtrImpl ( ) }
303+
304+ override string toString ( ) { result = AllocationExpr .super .toString ( ) }
305+ }
259306}
260307
261308/**
@@ -294,3 +341,85 @@ private class NewArrayAllocationExpr extends AllocationExpr, NewArrayExpr {
294341
295342 override predicate requiresDealloc ( ) { not exists ( this .getPlacementPointer ( ) ) }
296343}
344+
345+ private module HeuristicAllocation {
346+ private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr {
347+ override Expr getSizeExpr ( ) { result = AllocationExpr .super .getSizeExpr ( ) }
348+
349+ override int getSizeMult ( ) { result = AllocationExpr .super .getSizeMult ( ) }
350+
351+ override int getSizeBytes ( ) { result = AllocationExpr .super .getSizeBytes ( ) }
352+
353+ override Expr getReallocPtr ( ) { result = AllocationExpr .super .getReallocPtr ( ) }
354+
355+ override Type getAllocatedElementType ( ) {
356+ result = AllocationExpr .super .getAllocatedElementType ( )
357+ }
358+
359+ override predicate requiresDealloc ( ) { AllocationExpr .super .requiresDealloc ( ) }
360+ }
361+
362+ private class HeuristicAllocationFunctionModeled extends HeuristicAllocationFunction instanceof AllocationFunction {
363+ override int getSizeArg ( ) { result = AllocationFunction .super .getSizeArg ( ) }
364+
365+ override int getSizeMult ( ) { result = AllocationFunction .super .getSizeMult ( ) }
366+
367+ override int getReallocPtrArg ( ) { result = AllocationFunction .super .getReallocPtrArg ( ) }
368+
369+ override predicate requiresDealloc ( ) { AllocationFunction .super .requiresDealloc ( ) }
370+ }
371+
372+ private int getAnUnsignedParameter ( Function f ) {
373+ f .getParameter ( result ) .getUnspecifiedType ( ) .( IntegralType ) .isUnsigned ( )
374+ }
375+
376+ private int getAPointerParameter ( Function f ) {
377+ f .getParameter ( result ) .getUnspecifiedType ( ) instanceof PointerType
378+ }
379+
380+ private class HeuristicAllocationFunctionByName extends HeuristicAllocationFunction instanceof Function {
381+ int sizeArg ;
382+
383+ HeuristicAllocationFunctionByName ( ) {
384+ Function .super .getName ( ) .matches ( "%alloc%" ) and
385+ Function .super .getUnspecifiedType ( ) instanceof PointerType and
386+ sizeArg = unique( | | getAnUnsignedParameter ( this ) )
387+ }
388+
389+ override int getSizeArg ( ) { result = sizeArg }
390+
391+ override int getReallocPtrArg ( ) {
392+ Function .super .getName ( ) .matches ( "%realloc%" ) and
393+ result = unique( | | getAPointerParameter ( this ) )
394+ }
395+
396+ override predicate requiresDealloc ( ) { none ( ) }
397+ }
398+
399+ private int getReallocPtrArg ( HeuristicAllocationFunction f ) { result = f .getReallocPtrArg ( ) }
400+
401+ private int getSizeArg ( HeuristicAllocationFunction f ) { result = f .getSizeArg ( ) }
402+
403+ private int getSizeMult ( HeuristicAllocationFunction f ) { result = f .getSizeMult ( ) }
404+
405+ private predicate requiresDealloc ( HeuristicAllocationFunction f ) { f .requiresDealloc ( ) }
406+
407+ private class Base =
408+ CallAllocationExprBase< HeuristicAllocationFunction > :: With< getReallocPtrArg / 1 , getSizeArg / 1 , getSizeMult / 1 , requiresDealloc / 1 > :: CallAllocationExprImpl ;
409+
410+ private class CallAllocationExpr extends HeuristicAllocationExpr , Base {
411+ override Expr getSizeExpr ( ) { result = super .getSizeExprImpl ( ) }
412+
413+ override int getSizeMult ( ) { result = super .getSizeMultImpl ( ) }
414+
415+ override Type getAllocatedElementType ( ) { result = super .getAllocatedElementTypeImpl ( ) }
416+
417+ override predicate requiresDealloc ( ) { super .requiresDeallocImpl ( ) }
418+
419+ override int getSizeBytes ( ) { result = super .getSizeBytesImpl ( ) }
420+
421+ override Expr getReallocPtr ( ) { result = super .getReallocPtrImpl ( ) }
422+
423+ override string toString ( ) { result = HeuristicAllocationExpr .super .toString ( ) }
424+ }
425+ }
0 commit comments