@@ -13,8 +13,9 @@ import codingstandards.cpp.PossiblyUnsafeStringOperation
13
13
import codingstandards.cpp.SimpleRangeAnalysisCustomizations
14
14
import semmle.code.cpp.dataflow.DataFlow
15
15
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16
+ import semmle.code.cpp.security.BufferWrite
16
17
17
- module OutOfBounds {
18
+ module OOB {
18
19
bindingset [ name, result ]
19
20
private string getNameOrInternalName ( string name ) {
20
21
result = name or
@@ -312,7 +313,7 @@ module OutOfBounds {
312
313
*/
313
314
class SimpleStringLibraryFunction extends BufferAccessLibraryFunction {
314
315
SimpleStringLibraryFunction ( ) {
315
- this = libraryFunctionNameParamTable ( this .getName ( ) , _, _, _ , _ )
316
+ this = libraryFunctionNameParamTableSimpleString ( this .getName ( ) , _, _, - 1 , - 1 )
316
317
}
317
318
318
319
override predicate getANullTerminatedParameterIndex ( int i ) {
@@ -405,9 +406,11 @@ module OutOfBounds {
405
406
}
406
407
}
407
408
409
+ class SimpleStringLibraryFunctionCall extends BufferAccessLibraryFunctionCall {
410
+ SimpleStringLibraryFunctionCall ( ) { this .getTarget ( ) instanceof SimpleStringLibraryFunction }
411
+ }
412
+
408
413
int getStatedAllocValue ( Expr e ) {
409
- // `upperBound(e)` defaults to `exprMaxVal(e)` when `e` isn't analyzable. So to get a meaningful
410
- // result in this case we pick the minimum value obtainable from dataflow and range analysis.
411
414
if upperBound ( e ) = exprMaxVal ( e )
412
415
then result = max ( Expr source | DataFlow:: localExprFlow ( source , e ) | source .getValue ( ) .toInt ( ) )
413
416
else
@@ -620,6 +623,26 @@ module OutOfBounds {
620
623
)
621
624
)
622
625
}
626
+
627
+ override predicate isBarrierOut ( DataFlow:: Node node ) {
628
+ // the default interprocedural data-flow model flows through any array assignment expressions
629
+ // to the qualifier (array base or pointer dereferenced) instead of the individual element
630
+ // that the assignment modifies. this default behaviour causes false positives for any future
631
+ // access of the array base, so remove the assignment edge at the expense of false-negatives.
632
+ exists ( AssignExpr a |
633
+ node .asExpr ( ) = a .getRValue ( ) .getAChild * ( ) and
634
+ (
635
+ a .getLValue ( ) instanceof ArrayExpr or
636
+ a .getLValue ( ) instanceof PointerDereferenceExpr
637
+ )
638
+ )
639
+ or
640
+ // remove flow from `src` to `dst` in memcpy
641
+ exists ( FunctionCall fc |
642
+ fc .getTarget ( ) .getName ( ) = getNameOrInternalName ( "memcpy" ) and
643
+ node .asExpr ( ) = fc .getArgument ( 1 ) .getAChild * ( )
644
+ )
645
+ }
623
646
}
624
647
625
648
predicate hasFlowFromBufferOrSizeExprToUse ( Expr source , Expr use ) {
@@ -695,31 +718,25 @@ module OutOfBounds {
695
718
hasFlowFromBufferOrSizeExprToUse ( allocSize , bufferSizeArg )
696
719
}
697
720
698
- predicate isBufferSizeExprGreaterThanSourceSizeExpr (
699
- Expr bufferUse , Expr bufferSize , Expr sizeSource , PointerToObjectSource sourceBufferAllocation ,
700
- int bufSize , int size , BufferAccessLibraryFunctionCall fc , int offset , Expr base
721
+ predicate isSizeArgGreaterThanBufferSize (
722
+ Expr bufferArg , Expr sizeArg , PointerToObjectSource bufferSource , int bufferArgSize ,
723
+ int sizeArgValue , BufferAccessLibraryFunctionCall fc
701
724
) {
702
725
exists ( float sizeMult |
703
726
(
704
- bufferUse = fc .getWriteArg ( ) and
705
- bufferSize = fc .getWriteSizeArg ( ) and
727
+ bufferArg = fc .getWriteArg ( ) and
728
+ sizeArg = fc .getWriteSizeArg ( ) and
706
729
sizeMult = fc .getWriteSizeArgMult ( )
707
730
or
708
- bufferUse = fc .getReadArg ( ) and
709
- bufferSize = fc .getReadSizeArg ( ) and
731
+ bufferArg = fc .getReadArg ( ) and
732
+ sizeArg = fc .getReadSizeArg ( ) and
710
733
sizeMult = fc .getReadSizeArgMult ( )
711
734
) and
712
735
(
713
- offset = 0 and
714
- base = bufferSize and
715
- bufferUseComputableBufferSize ( bufferUse , sourceBufferAllocation , bufSize ) and
716
- sizeExprComputableSize ( bufferSize , sizeSource , size ) and
717
- (
718
- bufSize - getArithmeticOffsetValue ( bufferUse ) <
719
- ( sizeMult * ( size + getArithmeticOffsetValue ( bufferSize ) ) .( float ) )
720
- or
721
- size = 0
722
- )
736
+ bufferUseComputableBufferSize ( bufferArg , bufferSource , bufferArgSize ) and
737
+ sizeExprComputableSize ( sizeArg , _, sizeArgValue ) and
738
+ bufferArgSize - getArithmeticOffsetValue ( bufferArg ) <
739
+ sizeMult .( float ) * ( sizeArgValue + getArithmeticOffsetValue ( sizeArg ) ) .( float )
723
740
)
724
741
)
725
742
}
@@ -741,32 +758,45 @@ module OutOfBounds {
741
758
sourceSizeExpr = source .getSizeExprSource ( sourceSizeExprBase , sourceSizeExprOffset ) and
742
759
bufferUseNonComputableSize ( bufferUse , source ) and
743
760
not globalValueNumber ( sourceSizeExpr ) = globalValueNumber ( bufferSize ) and
744
- exists ( Expr offsetExpr |
745
- offsetExpr = bufferSize .getAChild * ( ) and
746
- sizeArgOffset = getArithmeticOffsetValue ( offsetExpr )
747
- ) and
761
+ sizeArgOffset = getArithmeticOffsetValue ( bufferSize .getAChild * ( ) ) and
748
762
bufferArgOffset = getArithmeticOffsetValue ( bufferUse ) and
749
763
sourceSizeExprOffset + bufferArgOffset < sizeArgOffset
750
764
}
751
765
752
- predicate problems ( BufferAccessLibraryFunctionCall fc , string msg ) {
753
- exists ( Expr bufferUse , PointerToObjectSource source |
754
- exists ( int bufSize , int size , Expr bufferSize , Expr sizeSource |
755
- isBufferSizeExprGreaterThanSourceSizeExpr ( bufferUse , bufferSize , sizeSource , source ,
756
- bufSize , size , fc , _, _) and
757
- msg = "Buffer size is smaller than size arg."
758
- )
759
- or
760
- exists ( int i |
761
- fc .getTarget ( ) .( BufferAccessLibraryFunction ) .getANullTerminatedParameterIndex ( i ) and
762
- fc .getArgument ( i ) = bufferUse and
763
- source .isNotNullTerminated ( ) and
764
- hasFlowFromBufferOrSizeExprToUse ( source , bufferUse .getAChild * ( ) ) and
765
- msg = "Buffer " + bufferUse .toString ( ) + " is not null-terminated."
766
- )
767
- or
768
- isBufferSizeOffsetOfGVN ( fc , _, bufferUse , source , _, _, _, _, _, _) and
769
- msg = "Buffer size is offset of GVN."
766
+ predicate isMandatoryBufferArgNull ( Expr bufferArg , BufferAccessLibraryFunctionCall fc ) {
767
+ exists ( int i |
768
+ i =
769
+ [
770
+ fc .getTarget ( ) .( BufferAccessLibraryFunction ) .getReadParamIndex ( ) ,
771
+ fc .getTarget ( ) .( BufferAccessLibraryFunction ) .getWriteParamIndex ( )
772
+ ] and
773
+ not fc .getTarget ( ) .( BufferAccessLibraryFunction ) .getAPermissiblyNullParameterIndex ( i ) and
774
+ bufferArg = fc .getArgument ( i ) and
775
+ getStatedValue ( bufferArg ) = 0
776
+ )
777
+ }
778
+
779
+ predicate isNullTerminatorMissingFromBufferArg (
780
+ Expr bufferArg , PointerToObjectSource source , BufferAccessLibraryFunctionCall fc
781
+ ) {
782
+ exists ( int i |
783
+ fc .getTarget ( ) .( BufferAccessLibraryFunction ) .getANullTerminatedParameterIndex ( i ) and
784
+ fc .getArgument ( i ) = bufferArg and
785
+ source .isNotNullTerminated ( ) and
786
+ hasFlowFromBufferOrSizeExprToUse ( source , bufferArg .getAChild * ( ) )
787
+ )
788
+ }
789
+
790
+ predicate isReadBufferSizeSmallerThanWriteBufferSize (
791
+ Expr readBuffer , Expr writeBuffer , SimpleStringLibraryFunctionCall fc
792
+ ) {
793
+ readBuffer = fc .getReadArg ( ) and
794
+ writeBuffer = fc .getWriteArg ( ) and
795
+ exists ( int readBufferSize , int writeBufferSize |
796
+ bufferUseComputableBufferSize ( readBuffer , _, readBufferSize ) and
797
+ bufferUseComputableBufferSize ( writeBuffer , _, writeBufferSize ) and
798
+ readBufferSize - getArithmeticOffsetValue ( readBuffer ) <
799
+ writeBufferSize - getArithmeticOffsetValue ( writeBuffer )
770
800
)
771
801
}
772
802
}
0 commit comments