mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
C++: Define an extractor version table and use in IR generation
This commit is contained in:
2226
cpp/downgrades/f79ce79e3b751aeeed59e594633ba5c07a27ef3e/old.dbscheme
Normal file
2226
cpp/downgrades/f79ce79e3b751aeeed59e594633ba5c07a27ef3e/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: Introduce extractor version numbers
|
||||||
|
compatibility: breaking
|
||||||
|
extractor_version.rel: delete
|
||||||
10
cpp/ql/lib/semmle/code/cpp/internal/ExtractorVersion.qll
Normal file
10
cpp/ql/lib/semmle/code/cpp/internal/ExtractorVersion.qll
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* INTERNAL: Do not use. Provides predicates for getting the CodeQL and frontend
|
||||||
|
* version used during database extraction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Get the extractor CodeQL version */
|
||||||
|
string getExtractorCodeQLVersion() { extractor_version(result, _) }
|
||||||
|
|
||||||
|
/** Get the extractor frontend version */
|
||||||
|
string getExtractorFrontendVersion() { extractor_version(_, result) }
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
private import cpp
|
private import cpp
|
||||||
import semmle.code.cpp.ir.implementation.raw.IR
|
import semmle.code.cpp.ir.implementation.raw.IR
|
||||||
|
private import semmle.code.cpp.internal.ExtractorVersion
|
||||||
private import semmle.code.cpp.ir.IRConfiguration
|
private import semmle.code.cpp.ir.IRConfiguration
|
||||||
private import semmle.code.cpp.ir.implementation.Opcode
|
private import semmle.code.cpp.ir.implementation.Opcode
|
||||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||||
@@ -362,10 +363,10 @@ predicate ignoreLoad(Expr expr) {
|
|||||||
expr instanceof FunctionAccess
|
expr instanceof FunctionAccess
|
||||||
or
|
or
|
||||||
// The load is duplicated from the operand.
|
// The load is duplicated from the operand.
|
||||||
expr instanceof ParenthesisExpr
|
exists(getExtractorFrontendVersion()) and expr instanceof ParenthesisExpr
|
||||||
or
|
or
|
||||||
// The load is duplicated from the right operand.
|
// The load is duplicated from the right operand.
|
||||||
expr instanceof CommaExpr
|
exists(getExtractorFrontendVersion()) and expr instanceof CommaExpr
|
||||||
or
|
or
|
||||||
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
|
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
|
||||||
instanceof FunctionPointerType
|
instanceof FunctionPointerType
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
private import cpp
|
private import cpp
|
||||||
|
private import semmle.code.cpp.internal.ExtractorVersion
|
||||||
private import semmle.code.cpp.ir.implementation.IRType
|
private import semmle.code.cpp.ir.implementation.IRType
|
||||||
private import semmle.code.cpp.ir.implementation.Opcode
|
private import semmle.code.cpp.ir.implementation.Opcode
|
||||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||||
@@ -648,7 +649,21 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr {
|
|||||||
class TranslatedPrefixCrementOperation extends TranslatedCrementOperation {
|
class TranslatedPrefixCrementOperation extends TranslatedCrementOperation {
|
||||||
override PrefixCrementOperation expr;
|
override PrefixCrementOperation expr;
|
||||||
|
|
||||||
override Instruction getResult() { result = this.getUnloadedOperand().getResult() }
|
override Instruction getResult() {
|
||||||
|
// The following distinction is needed to work around extractor limitations
|
||||||
|
// in old versions of the extractor.
|
||||||
|
if expr.isPRValueCategory() and not exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
|
// If this is C, then the result of a prefix crement is a prvalue for the
|
||||||
|
// new value assigned to the operand. If this is C++, then the result is
|
||||||
|
// an lvalue, but that lvalue is being loaded as part of this expression.
|
||||||
|
// EDG doesn't mark this as a load.
|
||||||
|
result = this.getInstruction(CrementOpTag())
|
||||||
|
else
|
||||||
|
// This is C++, where the result is an lvalue for the operand, and that
|
||||||
|
// lvalue is not being loaded as part of this expression.
|
||||||
|
result = this.getUnloadedOperand().getResult()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TranslatedPostfixCrementOperation extends TranslatedCrementOperation {
|
class TranslatedPostfixCrementOperation extends TranslatedCrementOperation {
|
||||||
@@ -1491,7 +1506,21 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
|
|||||||
result = this.getRightOperand().getFirstInstruction()
|
result = this.getRightOperand().getFirstInstruction()
|
||||||
}
|
}
|
||||||
|
|
||||||
final override Instruction getResult() { result = this.getLeftOperand().getResult() }
|
final override Instruction getResult() {
|
||||||
|
// The following distinction is needed to work around extractor limitations
|
||||||
|
// in old versions of the extractor.
|
||||||
|
if expr.isPRValueCategory() and not exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
|
// If this is C, then the result of an assignment is a prvalue for the new
|
||||||
|
// value assigned to the left operand. If this is C++, then the result is
|
||||||
|
// an lvalue, but that lvalue is being loaded as part of this expression.
|
||||||
|
// EDG doesn't mark this as a load.
|
||||||
|
result = this.getRightOperand().getResult()
|
||||||
|
else
|
||||||
|
// This is C++, where the result is an lvalue for the left operand,
|
||||||
|
// and that lvalue is not being loaded as part of this expression.
|
||||||
|
result = this.getLeftOperand().getResult()
|
||||||
|
}
|
||||||
|
|
||||||
final TranslatedExpr getLeftOperand() {
|
final TranslatedExpr getLeftOperand() {
|
||||||
result = getTranslatedExpr(expr.getLValue().getFullyConverted())
|
result = getTranslatedExpr(expr.getLValue().getFullyConverted())
|
||||||
@@ -1617,7 +1646,21 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr {
|
|||||||
result = this.getRightOperand().getFirstInstruction()
|
result = this.getRightOperand().getFirstInstruction()
|
||||||
}
|
}
|
||||||
|
|
||||||
final override Instruction getResult() { result = this.getUnloadedLeftOperand().getResult() }
|
final override Instruction getResult() {
|
||||||
|
// The following distinction is needed to work around extractor limitations
|
||||||
|
// in old versions of the extractor.
|
||||||
|
if expr.isPRValueCategory() and not exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
|
// If this is C, then the result of an assignment is a prvalue for the new
|
||||||
|
// value assigned to the left operand. If this is C++, then the result is
|
||||||
|
// an lvalue, but that lvalue is being loaded as part of this expression.
|
||||||
|
// EDG doesn't mark this as a load.
|
||||||
|
result = this.getStoredValue()
|
||||||
|
else
|
||||||
|
// This is C++, where the result is an lvalue for the left operand,
|
||||||
|
// and that lvalue is not being loaded as part of this expression.
|
||||||
|
result = this.getUnloadedLeftOperand().getResult()
|
||||||
|
}
|
||||||
|
|
||||||
final TranslatedExpr getUnloadedLeftOperand() {
|
final TranslatedExpr getUnloadedLeftOperand() {
|
||||||
result = this.getLoadedLeftOperand().getOperand()
|
result = this.getLoadedLeftOperand().getOperand()
|
||||||
@@ -2155,15 +2198,16 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
|||||||
not this.elseIsVoid() and tag = ConditionValueFalseStoreTag()
|
not this.elseIsVoid() and tag = ConditionValueFalseStoreTag()
|
||||||
) and
|
) and
|
||||||
opcode instanceof Opcode::Store and
|
opcode instanceof Opcode::Store and
|
||||||
(
|
if exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
not expr.hasLValueToRValueConversion() and
|
not expr.hasLValueToRValueConversion() and
|
||||||
resultType = this.getResultType()
|
resultType = this.getResultType()
|
||||||
or
|
or
|
||||||
expr.hasLValueToRValueConversion() and
|
expr.hasLValueToRValueConversion() and
|
||||||
resultType = getTypeForPRValue(expr.getType())
|
resultType = getTypeForPRValue(expr.getType())
|
||||||
)
|
else resultType = this.getResultType()
|
||||||
or
|
or
|
||||||
not expr.hasLValueToRValueConversion() and
|
(not expr.hasLValueToRValueConversion() or not exists(getExtractorFrontendVersion())) and
|
||||||
tag = ConditionValueResultLoadTag() and
|
tag = ConditionValueResultLoadTag() and
|
||||||
opcode instanceof Opcode::Load and
|
opcode instanceof Opcode::Load and
|
||||||
resultType = this.getResultType()
|
resultType = this.getResultType()
|
||||||
@@ -2193,15 +2237,16 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
tag = ConditionValueResultTempAddressTag() and
|
tag = ConditionValueResultTempAddressTag() and
|
||||||
(
|
if exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
not expr.hasLValueToRValueConversion() and
|
not expr.hasLValueToRValueConversion() and
|
||||||
result = this.getInstruction(ConditionValueResultLoadTag())
|
result = this.getInstruction(ConditionValueResultLoadTag())
|
||||||
or
|
or
|
||||||
expr.hasLValueToRValueConversion() and
|
expr.hasLValueToRValueConversion() and
|
||||||
result = this.getParent().getChildSuccessor(this)
|
result = this.getParent().getChildSuccessor(this)
|
||||||
)
|
else result = this.getInstruction(ConditionValueResultLoadTag())
|
||||||
or
|
or
|
||||||
not expr.hasLValueToRValueConversion() and
|
(not expr.hasLValueToRValueConversion() or not exists(getExtractorFrontendVersion())) and
|
||||||
tag = ConditionValueResultLoadTag() and
|
tag = ConditionValueResultLoadTag() and
|
||||||
result = this.getParent().getChildSuccessor(this)
|
result = this.getParent().getChildSuccessor(this)
|
||||||
)
|
)
|
||||||
@@ -2230,7 +2275,7 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
|||||||
result = this.getElse().getResult()
|
result = this.getElse().getResult()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
not expr.hasLValueToRValueConversion() and
|
(not expr.hasLValueToRValueConversion() or not exists(getExtractorFrontendVersion())) and
|
||||||
tag = ConditionValueResultLoadTag() and
|
tag = ConditionValueResultLoadTag() and
|
||||||
operandTag instanceof AddressOperandTag and
|
operandTag instanceof AddressOperandTag and
|
||||||
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
||||||
@@ -2240,13 +2285,14 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
|||||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||||
not this.resultIsVoid() and
|
not this.resultIsVoid() and
|
||||||
tag = ConditionValueTempVar() and
|
tag = ConditionValueTempVar() and
|
||||||
(
|
if exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
not expr.hasLValueToRValueConversion() and
|
not expr.hasLValueToRValueConversion() and
|
||||||
type = this.getResultType()
|
type = this.getResultType()
|
||||||
or
|
or
|
||||||
expr.hasLValueToRValueConversion() and
|
expr.hasLValueToRValueConversion() and
|
||||||
type = getTypeForPRValue(expr.getType())
|
type = getTypeForPRValue(expr.getType())
|
||||||
)
|
else type = this.getResultType()
|
||||||
}
|
}
|
||||||
|
|
||||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||||
@@ -2261,13 +2307,14 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
|||||||
|
|
||||||
final override Instruction getResult() {
|
final override Instruction getResult() {
|
||||||
not this.resultIsVoid() and
|
not this.resultIsVoid() and
|
||||||
(
|
if exists(getExtractorFrontendVersion())
|
||||||
|
then
|
||||||
expr.hasLValueToRValueConversion() and
|
expr.hasLValueToRValueConversion() and
|
||||||
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
||||||
or
|
or
|
||||||
not expr.hasLValueToRValueConversion() and
|
not expr.hasLValueToRValueConversion() and
|
||||||
result = this.getInstruction(ConditionValueResultLoadTag())
|
result = this.getInstruction(ConditionValueResultLoadTag())
|
||||||
)
|
else result = this.getInstruction(ConditionValueResultLoadTag())
|
||||||
}
|
}
|
||||||
|
|
||||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||||
@@ -3226,9 +3273,19 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) {
|
|||||||
(
|
(
|
||||||
expr instanceof AssignExpr
|
expr instanceof AssignExpr
|
||||||
or
|
or
|
||||||
expr instanceof AssignOperation
|
expr instanceof AssignOperation and
|
||||||
|
(
|
||||||
|
not expr.isPRValueCategory() // is C++
|
||||||
|
or
|
||||||
|
exists(getExtractorFrontendVersion())
|
||||||
|
)
|
||||||
or
|
or
|
||||||
expr instanceof PrefixCrementOperation
|
expr instanceof PrefixCrementOperation and
|
||||||
|
(
|
||||||
|
not expr.isPRValueCategory() // is C++
|
||||||
|
or
|
||||||
|
exists(getExtractorFrontendVersion())
|
||||||
|
)
|
||||||
or
|
or
|
||||||
// Because the load is on the `e` in `e++`.
|
// Because the load is on the `e` in `e++`.
|
||||||
expr instanceof PostfixCrementOperation
|
expr instanceof PostfixCrementOperation
|
||||||
|
|||||||
@@ -197,6 +197,11 @@ svnchurn(
|
|||||||
* C++ dbscheme
|
* C++ dbscheme
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extractor_version(
|
||||||
|
string codeql_version: string ref,
|
||||||
|
string frontend_version: string ref
|
||||||
|
)
|
||||||
|
|
||||||
@location = @location_stmt | @location_expr | @location_default ;
|
@location = @location_stmt | @location_expr | @location_default ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
description: Introduce extractor version numbers
|
||||||
|
compatibility: full
|
||||||
Reference in New Issue
Block a user