ਸਾਡੇ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM ਪ੍ਰੋਜੈਕਟ ਦੀ ਆਖਰੀ ਕੋਡ ਜਾਂਚ ਤੋਂ ਦੋ ਸਾਲ ਤੋਂ ਵੱਧ ਸਮਾਂ ਬੀਤ ਚੁੱਕਾ ਹੈ। ਆਓ ਇਹ ਯਕੀਨੀ ਕਰੀਏ ਕਿ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਅਜੇ ਵੀ ਤਰੁੱਟੀਆਂ ਅਤੇ ਸੰਭਾਵੀ ਕਮਜ਼ੋਰੀਆਂ ਦੀ ਪਛਾਣ ਕਰਨ ਲਈ ਇੱਕ ਪ੍ਰਮੁੱਖ ਸਾਧਨ ਹੈ। ਅਜਿਹਾ ਕਰਨ ਲਈ, ਅਸੀਂ LLVM 8.0.0 ਰੀਲੀਜ਼ ਵਿੱਚ ਨਵੀਆਂ ਗਲਤੀਆਂ ਦੀ ਜਾਂਚ ਕਰਾਂਗੇ ਅਤੇ ਲੱਭਾਂਗੇ।
ਲੇਖ ਲਿਖਿਆ ਜਾਣਾ ਹੈ
ਇਮਾਨਦਾਰ ਹੋਣ ਲਈ, ਮੈਂ ਇਹ ਲੇਖ ਨਹੀਂ ਲਿਖਣਾ ਚਾਹੁੰਦਾ ਸੀ. ਕਿਸੇ ਪ੍ਰੋਜੈਕਟ ਬਾਰੇ ਲਿਖਣਾ ਦਿਲਚਸਪ ਨਹੀਂ ਹੈ ਜਿਸਦੀ ਅਸੀਂ ਪਹਿਲਾਂ ਹੀ ਕਈ ਵਾਰ ਜਾਂਚ ਕਰ ਚੁੱਕੇ ਹਾਂ (
ਹਰ ਵਾਰ ਜਦੋਂ LLVM ਦਾ ਨਵਾਂ ਸੰਸਕਰਣ ਜਾਰੀ ਜਾਂ ਅਪਡੇਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ
ਦੇਖੋ, ਕਲੈਂਗ ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ ਦੇ ਨਵੇਂ ਸੰਸਕਰਣ ਨੇ ਨਵੀਆਂ ਗਲਤੀਆਂ ਲੱਭਣਾ ਸਿੱਖ ਲਿਆ ਹੈ! ਇਹ ਮੈਨੂੰ ਜਾਪਦਾ ਹੈ ਕਿ ਪੀਵੀਐਸ-ਸਟੂਡੀਓ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਸਾਰਥਕਤਾ ਘੱਟ ਰਹੀ ਹੈ. Clang ਪਹਿਲਾਂ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਤਰੁੱਟੀਆਂ ਲੱਭਦਾ ਹੈ ਅਤੇ PVS-ਸਟੂਡੀਓ ਦੀਆਂ ਸਮਰੱਥਾਵਾਂ ਨੂੰ ਫੜਦਾ ਹੈ। ਤੁਸੀਂ ਇਸ ਬਾਰੇ ਕੀ ਸੋਚਦੇ ਹੋ?
ਇਸ ਲਈ ਮੈਂ ਹਮੇਸ਼ਾ ਕੁਝ ਅਜਿਹਾ ਜਵਾਬ ਦੇਣਾ ਚਾਹੁੰਦਾ ਹਾਂ:
ਅਸੀਂ ਵੀ ਵਿਹਲੇ ਨਹੀਂ ਬੈਠਦੇ! ਅਸੀਂ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀਆਂ ਸਮਰੱਥਾਵਾਂ ਵਿੱਚ ਮਹੱਤਵਪੂਰਨ ਸੁਧਾਰ ਕੀਤਾ ਹੈ। ਇਸ ਲਈ ਚਿੰਤਾ ਨਾ ਕਰੋ, ਅਸੀਂ ਪਹਿਲਾਂ ਵਾਂਗ ਅਗਵਾਈ ਕਰਦੇ ਰਹਿੰਦੇ ਹਾਂ।
ਬਦਕਿਸਮਤੀ ਨਾਲ, ਇਹ ਇੱਕ ਬੁਰਾ ਜਵਾਬ ਹੈ. ਇਸ ਵਿੱਚ ਕੋਈ ਸਬੂਤ ਨਹੀਂ ਹਨ। ਅਤੇ ਇਸ ਲਈ ਮੈਂ ਹੁਣ ਇਹ ਲੇਖ ਲਿਖ ਰਿਹਾ ਹਾਂ. ਇਸ ਲਈ, ਐਲਐਲਵੀਐਮ ਪ੍ਰੋਜੈਕਟ ਦੀ ਇੱਕ ਵਾਰ ਫਿਰ ਜਾਂਚ ਕੀਤੀ ਗਈ ਹੈ ਅਤੇ ਇਸ ਵਿੱਚ ਕਈ ਤਰ੍ਹਾਂ ਦੀਆਂ ਤਰੁੱਟੀਆਂ ਪਾਈਆਂ ਗਈਆਂ ਹਨ। ਮੈਂ ਹੁਣ ਉਹਨਾਂ ਦਾ ਪ੍ਰਦਰਸ਼ਨ ਕਰਾਂਗਾ ਜੋ ਮੈਨੂੰ ਦਿਲਚਸਪ ਲੱਗਦੇ ਸਨ। ਕਲੈਂਗ ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ ਇਹ ਤਰੁੱਟੀਆਂ ਨਹੀਂ ਲੱਭ ਸਕਦਾ (ਜਾਂ ਇਸਦੀ ਮਦਦ ਨਾਲ ਅਜਿਹਾ ਕਰਨਾ ਬਹੁਤ ਅਸੁਵਿਧਾਜਨਕ ਹੈ)। ਪਰ ਅਸੀਂ ਕਰ ਸਕਦੇ ਹਾਂ। ਇਸ ਤੋਂ ਇਲਾਵਾ, ਮੈਂ ਇੱਕ ਸ਼ਾਮ ਵਿੱਚ ਇਹ ਸਾਰੀਆਂ ਗਲਤੀਆਂ ਲੱਭੀਆਂ ਅਤੇ ਲਿਖ ਦਿੱਤੀਆਂ।
ਪਰ ਲੇਖ ਲਿਖਣ ਵਿੱਚ ਕਈ ਹਫ਼ਤੇ ਲੱਗ ਗਏ। ਮੈਂ ਇਹ ਸਭ ਟੈਕਸਟ ਵਿੱਚ ਪਾਉਣ ਲਈ ਆਪਣੇ ਆਪ ਨੂੰ ਨਹੀਂ ਲਿਆ ਸਕਿਆ :).
ਤਰੀਕੇ ਨਾਲ, ਜੇ ਤੁਸੀਂ ਇਸ ਵਿੱਚ ਦਿਲਚਸਪੀ ਰੱਖਦੇ ਹੋ ਕਿ ਪੀਵੀਐਸ-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਵਿੱਚ ਗਲਤੀਆਂ ਅਤੇ ਸੰਭਾਵੀ ਕਮਜ਼ੋਰੀਆਂ ਦੀ ਪਛਾਣ ਕਰਨ ਲਈ ਕਿਹੜੀਆਂ ਤਕਨੀਕਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਮੈਂ ਇਸ ਤੋਂ ਜਾਣੂ ਹੋਣ ਦਾ ਸੁਝਾਅ ਦਿੰਦਾ ਹਾਂ
ਨਵੇਂ ਅਤੇ ਪੁਰਾਣੇ ਨਿਦਾਨ
ਜਿਵੇਂ ਕਿ ਪਹਿਲਾਂ ਹੀ ਨੋਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਲਗਭਗ ਦੋ ਸਾਲ ਪਹਿਲਾਂ LLVM ਪ੍ਰੋਜੈਕਟ ਦੀ ਇੱਕ ਵਾਰ ਫਿਰ ਜਾਂਚ ਕੀਤੀ ਗਈ ਸੀ, ਅਤੇ ਪਾਈਆਂ ਗਈਆਂ ਗਲਤੀਆਂ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ ਸੀ। ਹੁਣ ਇਹ ਲੇਖ ਗਲਤੀਆਂ ਦਾ ਇੱਕ ਨਵਾਂ ਬੈਚ ਪੇਸ਼ ਕਰੇਗਾ। ਨਵੇਂ ਬੱਗ ਕਿਉਂ ਮਿਲੇ? ਇਸਦੇ 3 ਕਾਰਨ ਹਨ:
- LLVM ਪ੍ਰੋਜੈਕਟ ਵਿਕਸਿਤ ਹੋ ਰਿਹਾ ਹੈ, ਪੁਰਾਣਾ ਕੋਡ ਬਦਲ ਰਿਹਾ ਹੈ ਅਤੇ ਨਵਾਂ ਕੋਡ ਜੋੜ ਰਿਹਾ ਹੈ। ਕੁਦਰਤੀ ਤੌਰ 'ਤੇ, ਸੰਸ਼ੋਧਿਤ ਅਤੇ ਲਿਖਤੀ ਕੋਡ ਵਿੱਚ ਨਵੀਆਂ ਗਲਤੀਆਂ ਹਨ. ਇਹ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਦਰਸਾਉਂਦਾ ਹੈ ਕਿ ਸਥਿਰ ਵਿਸ਼ਲੇਸ਼ਣ ਨੂੰ ਨਿਯਮਤ ਤੌਰ 'ਤੇ ਵਰਤਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ, ਅਤੇ ਕਦੇ-ਕਦਾਈਂ ਨਹੀਂ। ਸਾਡੇ ਲੇਖ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀਆਂ ਸਮਰੱਥਾਵਾਂ ਨੂੰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਦਿਖਾਉਂਦੇ ਹਨ, ਪਰ ਇਸਦਾ ਕੋਡ ਗੁਣਵੱਤਾ ਨੂੰ ਸੁਧਾਰਨ ਅਤੇ ਗਲਤੀਆਂ ਨੂੰ ਠੀਕ ਕਰਨ ਦੀ ਲਾਗਤ ਨੂੰ ਘਟਾਉਣ ਨਾਲ ਕੋਈ ਲੈਣਾ-ਦੇਣਾ ਨਹੀਂ ਹੈ। ਨਿਯਮਿਤ ਤੌਰ 'ਤੇ ਸਥਿਰ ਕੋਡ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀ ਵਰਤੋਂ ਕਰੋ!
- ਅਸੀਂ ਮੌਜੂਦਾ ਡਾਇਗਨੌਸਟਿਕਸ ਨੂੰ ਅੰਤਿਮ ਰੂਪ ਦੇ ਰਹੇ ਹਾਂ ਅਤੇ ਸੁਧਾਰ ਕਰ ਰਹੇ ਹਾਂ। ਇਸ ਲਈ, ਵਿਸ਼ਲੇਸ਼ਕ ਗਲਤੀਆਂ ਦੀ ਪਛਾਣ ਕਰ ਸਕਦਾ ਹੈ ਜੋ ਇਸਨੇ ਪਿਛਲੇ ਸਕੈਨ ਦੌਰਾਨ ਧਿਆਨ ਨਹੀਂ ਦਿੱਤਾ ਸੀ।
- PVS-Studio ਵਿੱਚ ਨਵੇਂ ਡਾਇਗਨੌਸਟਿਕਸ ਪ੍ਰਗਟ ਹੋਏ ਹਨ ਜੋ 2 ਸਾਲ ਪਹਿਲਾਂ ਮੌਜੂਦ ਨਹੀਂ ਸਨ। ਮੈਂ PVS-ਸਟੂਡੀਓ ਦੇ ਵਿਕਾਸ ਨੂੰ ਸਪਸ਼ਟ ਰੂਪ ਵਿੱਚ ਦਿਖਾਉਣ ਲਈ ਉਹਨਾਂ ਨੂੰ ਇੱਕ ਵੱਖਰੇ ਭਾਗ ਵਿੱਚ ਉਜਾਗਰ ਕਰਨ ਦਾ ਫੈਸਲਾ ਕੀਤਾ ਹੈ।
2 ਸਾਲ ਪਹਿਲਾਂ ਮੌਜੂਦ ਡਾਇਗਨੌਸਟਿਕਸ ਦੁਆਰਾ ਪਛਾਣੇ ਗਏ ਨੁਕਸ
Fragment N1: ਕਾਪੀ-ਪੇਸਟ
static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
if (Name == "addcarryx.u32" || // Added in 8.0
....
Name == "avx512.mask.cvtps2pd.128" || // Added in 7.0
Name == "avx512.mask.cvtps2pd.256" || // Added in 7.0
Name == "avx512.cvtusi2sd" || // Added in 7.0
Name.startswith("avx512.mask.permvar.") || // Added in 7.0 // <=
Name.startswith("avx512.mask.permvar.") || // Added in 7.0 // <=
Name == "sse2.pmulu.dq" || // Added in 7.0
Name == "sse41.pmuldq" || // Added in 7.0
Name == "avx2.pmulu.dq" || // Added in 7.0
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਇਹ ਦੋ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਕਿ ਨਾਮ ਸਬਸਟਰਿੰਗ "avx512.mask.permvar" ਨਾਲ ਸ਼ੁਰੂ ਹੁੰਦਾ ਹੈ। ਦੂਜੀ ਜਾਂਚ ਵਿੱਚ, ਉਹ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਕੁਝ ਹੋਰ ਲਿਖਣਾ ਚਾਹੁੰਦੇ ਸਨ, ਪਰ ਕਾਪੀ ਕੀਤੇ ਟੈਕਸਟ ਨੂੰ ਠੀਕ ਕਰਨਾ ਭੁੱਲ ਗਏ ਸਨ।
Fragment N2: ਟਾਈਪੋ
enum CXNameRefFlags {
CXNameRange_WantQualifier = 0x1,
CXNameRange_WantTemplateArgs = 0x2,
CXNameRange_WantSinglePiece = 0x4
};
void AnnotateTokensWorker::HandlePostPonedChildCursor(
CXCursor Cursor, unsigned StartTokenIndex) {
const auto flags = CXNameRange_WantQualifier | CXNameRange_WantQualifier;
....
}
ਚੇਤਾਵਨੀ PVS-ਸਟੂਡੀਓ: V501 '|' ਦੇ ਖੱਬੇ ਅਤੇ ਸੱਜੇ ਪਾਸੇ 'CXNameRange_WantQualifier' ਇੱਕੋ ਜਿਹੇ ਉਪ-ਸਮੀਕਰਨ ਹਨ। ਆਪਰੇਟਰ CIndex.cpp 7245
ਇੱਕ ਟਾਈਪੋ ਦੇ ਕਾਰਨ, ਇੱਕੋ ਨਾਮਕ ਸਥਿਰ ਦੋ ਵਾਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ CXNameRange_WantQualifier.
ਫਰੈਗਮੈਂਟ N3: ਆਪਰੇਟਰ ਦੀ ਤਰਜੀਹ ਨਾਲ ਉਲਝਣ
int PPCTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) {
....
if (ISD == ISD::EXTRACT_VECTOR_ELT && Index == ST->isLittleEndian() ? 1 : 0)
return 0;
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਮੇਰੇ ਵਿਚਾਰ ਵਿੱਚ, ਇਹ ਇੱਕ ਬਹੁਤ ਹੀ ਸੁੰਦਰ ਗਲਤੀ ਹੈ. ਹਾਂ, ਮੈਨੂੰ ਪਤਾ ਹੈ ਕਿ ਮੇਰੇ ਕੋਲ ਸੁੰਦਰਤਾ ਬਾਰੇ ਅਜੀਬ ਵਿਚਾਰ ਹਨ :).
ਹੁਣ, ਅਨੁਸਾਰ
(ISD == ISD::EXTRACT_VECTOR_ELT && (Index == ST->isLittleEndian())) ? 1 : 0
ਵਿਹਾਰਕ ਦ੍ਰਿਸ਼ਟੀਕੋਣ ਤੋਂ, ਅਜਿਹੀ ਸਥਿਤੀ ਦਾ ਕੋਈ ਅਰਥ ਨਹੀਂ ਹੈ, ਕਿਉਂਕਿ ਇਸਨੂੰ ਘਟਾਇਆ ਜਾ ਸਕਦਾ ਹੈ:
(ISD == ISD::EXTRACT_VECTOR_ELT && Index == ST->isLittleEndian())
ਇਹ ਇੱਕ ਸਪੱਸ਼ਟ ਗਲਤੀ ਹੈ. ਜ਼ਿਆਦਾਤਰ ਸੰਭਾਵਨਾ ਹੈ, ਉਹ ਇੱਕ ਵੇਰੀਏਬਲ ਨਾਲ 0/1 ਦੀ ਤੁਲਨਾ ਕਰਨਾ ਚਾਹੁੰਦੇ ਸਨ ਇੰਡੈਕਸ. ਕੋਡ ਨੂੰ ਠੀਕ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ ਟਰਨਰੀ ਓਪਰੇਟਰ ਦੇ ਆਲੇ-ਦੁਆਲੇ ਬਰੈਕਟ ਜੋੜਨ ਦੀ ਲੋੜ ਹੈ:
if (ISD == ISD::EXTRACT_VECTOR_ELT && Index == (ST->isLittleEndian() ? 1 : 0))
ਤਰੀਕੇ ਨਾਲ, ਟਰਨਰੀ ਓਪਰੇਟਰ ਬਹੁਤ ਖ਼ਤਰਨਾਕ ਹੈ ਅਤੇ ਲਾਜ਼ੀਕਲ ਗਲਤੀਆਂ ਨੂੰ ਭੜਕਾਉਂਦਾ ਹੈ. ਇਸ ਨਾਲ ਬਹੁਤ ਸਾਵਧਾਨ ਰਹੋ ਅਤੇ ਬਰੈਕਟਾਂ ਨਾਲ ਲਾਲਚੀ ਨਾ ਬਣੋ। ਮੈਂ ਇਸ ਵਿਸ਼ੇ 'ਤੇ ਵਧੇਰੇ ਵਿਸਥਾਰ ਨਾਲ ਦੇਖਿਆ
ਫ੍ਰੈਗਮੈਂਟ N4, N5: ਨਲ ਪੁਆਇੰਟਰ
Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
....
TypedInit *LHS = dyn_cast<TypedInit>(Result);
....
LHS = dyn_cast<TypedInit>(
UnOpInit::get(UnOpInit::CAST, LHS, StringRecTy::get())
->Fold(CurRec));
if (!LHS) {
Error(PasteLoc, Twine("can't cast '") + LHS->getAsString() +
"' to string");
return nullptr;
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਜੇ ਪੁਆਇੰਟਰ ਐਲਐਚਐਸ ਖਾਲੀ ਹੈ, ਇੱਕ ਚੇਤਾਵਨੀ ਜਾਰੀ ਕੀਤੀ ਜਾਣੀ ਚਾਹੀਦੀ ਹੈ. ਹਾਲਾਂਕਿ, ਇਸਦੀ ਬਜਾਏ, ਇਹ ਉਹੀ ਨਲ ਪੁਆਇੰਟਰ ਡੀਰੇਫਰੈਂਡ ਕੀਤਾ ਜਾਵੇਗਾ: LHS->getAsString().
ਇਹ ਇੱਕ ਬਹੁਤ ਹੀ ਆਮ ਸਥਿਤੀ ਹੈ ਜਦੋਂ ਇੱਕ ਗਲਤੀ ਹੈਂਡਲਰ ਵਿੱਚ ਇੱਕ ਗਲਤੀ ਛੁਪੀ ਹੁੰਦੀ ਹੈ, ਕਿਉਂਕਿ ਕੋਈ ਵੀ ਉਹਨਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ ਸਾਰੇ ਪਹੁੰਚਯੋਗ ਕੋਡ ਦੀ ਜਾਂਚ ਕਰਦੇ ਹਨ, ਭਾਵੇਂ ਇਹ ਕਿੰਨੀ ਵਾਰ ਵਰਤਿਆ ਗਿਆ ਹੋਵੇ। ਇਹ ਇੱਕ ਬਹੁਤ ਵਧੀਆ ਉਦਾਹਰਣ ਹੈ ਕਿ ਕਿਵੇਂ ਸਥਿਰ ਵਿਸ਼ਲੇਸ਼ਣ ਹੋਰ ਟੈਸਟਿੰਗ ਅਤੇ ਗਲਤੀ ਸੁਰੱਖਿਆ ਤਕਨੀਕਾਂ ਨੂੰ ਪੂਰਾ ਕਰਦਾ ਹੈ।
ਸਮਾਨ ਪੁਆਇੰਟਰ ਹੈਂਡਲਿੰਗ ਗਲਤੀ RHS ਹੇਠਾਂ ਦਿੱਤੇ ਕੋਡ ਵਿੱਚ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਗਈ ਹੈ: V522 [CWE-476] ਨਲ ਪੁਆਇੰਟਰ 'RHS' ਦਾ ਹਵਾਲਾ ਦੇਣਾ ਹੋ ਸਕਦਾ ਹੈ। TGParser.cpp 2186
Fragment N6: ਹਿਲਾਉਣ ਤੋਂ ਬਾਅਦ ਪੁਆਇੰਟਰ ਦੀ ਵਰਤੋਂ ਕਰਨਾ
static Expected<bool>
ExtractBlocks(....)
{
....
std::unique_ptr<Module> ProgClone = CloneModule(BD.getProgram(), VMap);
....
BD.setNewProgram(std::move(ProgClone)); // <=
MiscompiledFunctions.clear();
for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first); // <=
assert(NewF && "Function not found??");
MiscompiledFunctions.push_back(NewF);
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V522 [CWE-476] ਨਲ ਪੁਆਇੰਟਰ 'ਪ੍ਰੋਗਕਲੋਨ' ਦਾ ਹਵਾਲਾ ਦਿੱਤਾ ਜਾ ਸਕਦਾ ਹੈ। Miscompilation.cpp 601
ਸ਼ੁਰੂ ਵਿੱਚ ਇੱਕ ਸਮਾਰਟ ਪੁਆਇੰਟਰ ProgClone ਵਸਤੂ ਦਾ ਮਾਲਕ ਹੋਣਾ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ:
BD.setNewProgram(std::move(ProgClone));
ਅਸਲ ਵਿੱਚ, ਹੁਣ ProgClone ਇੱਕ ਨਲ ਪੁਆਇੰਟਰ ਹੈ। ਇਸ ਲਈ, ਇੱਕ ਨਲ ਪੁਆਇੰਟਰ ਡੀਰੇਫਰੈਂਸ ਬਿਲਕੁਲ ਹੇਠਾਂ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ:
Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);
ਪਰ, ਅਸਲ ਵਿੱਚ, ਅਜਿਹਾ ਨਹੀਂ ਹੋਵੇਗਾ! ਯਾਦ ਰੱਖੋ ਕਿ ਲੂਪ ਅਸਲ ਵਿੱਚ ਚਲਾਇਆ ਨਹੀਂ ਗਿਆ ਹੈ।
ਕੰਟੇਨਰ ਦੇ ਸ਼ੁਰੂ 'ਤੇ ਗਲਤ ਕੰਪਾਇਲ ਕੀਤੇ ਫੰਕਸ਼ਨ ਸਾਫ਼ ਕੀਤਾ:
MiscompiledFunctions.clear();
ਅੱਗੇ, ਇਸ ਕੰਟੇਨਰ ਦਾ ਆਕਾਰ ਲੂਪ ਸਥਿਤੀ ਵਿੱਚ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ:
for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {
ਇਹ ਦੇਖਣਾ ਆਸਾਨ ਹੈ ਕਿ ਲੂਪ ਸ਼ੁਰੂ ਨਹੀਂ ਹੁੰਦਾ। ਮੈਨੂੰ ਲਗਦਾ ਹੈ ਕਿ ਇਹ ਵੀ ਇੱਕ ਬੱਗ ਹੈ ਅਤੇ ਕੋਡ ਨੂੰ ਵੱਖਰੇ ਤੌਰ 'ਤੇ ਲਿਖਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।
ਅਜਿਹਾ ਲਗਦਾ ਹੈ ਕਿ ਅਸੀਂ ਗਲਤੀਆਂ ਦੀ ਮਸ਼ਹੂਰ ਸਮਾਨਤਾ ਦਾ ਸਾਹਮਣਾ ਕੀਤਾ ਹੈ! ਇੱਕ ਗਲਤੀ ਦੂਜੀ ਨੂੰ ਢੱਕ ਦਿੰਦੀ ਹੈ :)
Fragment N7: ਹਿਲਾਉਣ ਤੋਂ ਬਾਅਦ ਪੁਆਇੰਟਰ ਦੀ ਵਰਤੋਂ ਕਰਨਾ
static Expected<bool> TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
std::unique_ptr<Module> Safe) {
outs() << " Optimizing functions being tested: ";
std::unique_ptr<Module> Optimized =
BD.runPassesOn(Test.get(), BD.getPassesToRun());
if (!Optimized) {
errs() << " Error running this sequence of passes"
<< " on the input program!n";
BD.setNewProgram(std::move(Test)); // <=
BD.EmitProgressBitcode(*Test, "pass-error", false); // <=
if (Error E = BD.debugOptimizerCrash())
return std::move(E);
return false;
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V522 [CWE-476] ਨਲ ਪੁਆਇੰਟਰ 'ਟੈਸਟ' ਦਾ ਹਵਾਲਾ ਦਿੱਤਾ ਜਾ ਸਕਦਾ ਹੈ। Miscompilation.cpp 709
ਫਿਰ ਉਹੀ ਸਥਿਤੀ। ਪਹਿਲਾਂ, ਵਸਤੂ ਦੀ ਸਮੱਗਰੀ ਨੂੰ ਮੂਵ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਅਤੇ ਫਿਰ ਇਸਨੂੰ ਇਸ ਤਰ੍ਹਾਂ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ ਜਿਵੇਂ ਕਿ ਕੁਝ ਨਹੀਂ ਹੋਇਆ ਸੀ. ਮੈਂ ਇਸ ਸਥਿਤੀ ਨੂੰ ਪ੍ਰੋਗਰਾਮ ਕੋਡ ਵਿੱਚ ਅਕਸਰ C++ ਵਿੱਚ ਮੂਵਮੈਂਟ ਸਿਮੈਂਟਿਕਸ ਦੇ ਪ੍ਰਗਟ ਹੋਣ ਤੋਂ ਬਾਅਦ ਵੇਖਦਾ ਹਾਂ। ਇਹੀ ਕਾਰਨ ਹੈ ਕਿ ਮੈਨੂੰ C++ ਭਾਸ਼ਾ ਪਸੰਦ ਹੈ! ਤੁਹਾਡੀ ਆਪਣੀ ਲੱਤ ਨੂੰ ਸ਼ੂਟ ਕਰਨ ਦੇ ਹੋਰ ਅਤੇ ਹੋਰ ਜਿਆਦਾ ਨਵੇਂ ਤਰੀਕੇ ਹਨ. PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਕੋਲ ਹਮੇਸ਼ਾ ਕੰਮ ਹੋਵੇਗਾ :).
ਫਰੈਗਮੈਂਟ N8: ਨਲ ਪੁਆਇੰਟਰ
void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
uint32_t TypeId = Symbol.getTypeId();
auto Type = Symbol.getSession().getSymbolById(TypeId);
if (Type)
Printer << "<unknown-type>";
else
Type->dump(*this);
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V522 [CWE-476] ਨਲ ਪੁਆਇੰਟਰ 'ਟਾਈਪ' ਦਾ ਹਵਾਲਾ ਦਿੱਤਾ ਜਾ ਸਕਦਾ ਹੈ। PrettyFunctionDumper.cpp 233
ਗਲਤੀ ਹੈਂਡਲਰਾਂ ਤੋਂ ਇਲਾਵਾ, ਡੀਬੱਗਿੰਗ ਪ੍ਰਿੰਟਆਉਟ ਫੰਕਸ਼ਨਾਂ ਦੀ ਆਮ ਤੌਰ 'ਤੇ ਜਾਂਚ ਨਹੀਂ ਕੀਤੀ ਜਾਂਦੀ। ਸਾਡੇ ਸਾਹਮਣੇ ਅਜਿਹਾ ਹੀ ਮਾਮਲਾ ਹੈ। ਫੰਕਸ਼ਨ ਉਪਭੋਗਤਾ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ, ਜੋ ਆਪਣੀਆਂ ਸਮੱਸਿਆਵਾਂ ਨੂੰ ਹੱਲ ਕਰਨ ਦੀ ਬਜਾਏ, ਇਸਨੂੰ ਠੀਕ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕੀਤਾ ਜਾਵੇਗਾ.
ਸਹੀ:
if (Type)
Type->dump(*this);
else
Printer << "<unknown-type>";
ਫਰੈਗਮੈਂਟ N9: ਨਲ ਪੁਆਇੰਟਰ
void SearchableTableEmitter::collectTableEntries(
GenericTable &Table, const std::vector<Record *> &Items) {
....
RecTy *Ty = resolveTypes(Field.RecType, TI->getType());
if (!Ty) // <=
PrintFatalError(Twine("Field '") + Field.Name + "' of table '" +
Table.Name + "' has incompatible type: " +
Ty->getAsString() + " vs. " + // <=
TI->getType()->getAsString());
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V522 [CWE-476] ਨਲ ਪੁਆਇੰਟਰ 'Ty' ਦਾ ਹਵਾਲਾ ਦਿੱਤਾ ਜਾ ਸਕਦਾ ਹੈ। SearchableTableEmitter.cpp 614
ਮੈਨੂੰ ਲਗਦਾ ਹੈ ਕਿ ਸਭ ਕੁਝ ਸਪਸ਼ਟ ਹੈ ਅਤੇ ਵਿਆਖਿਆ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ.
Fragment N10: ਟਾਈਪੋ
bool FormatTokenLexer::tryMergeCSharpNullConditionals() {
....
auto &Identifier = *(Tokens.end() - 2);
auto &Question = *(Tokens.end() - 1);
....
Identifier->ColumnWidth += Question->ColumnWidth;
Identifier->Type = Identifier->Type; // <=
Tokens.erase(Tokens.end() - 1);
return true;
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਆਪਣੇ ਆਪ ਨੂੰ ਇੱਕ ਵੇਰੀਏਬਲ ਨਿਰਧਾਰਤ ਕਰਨ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ. ਜ਼ਿਆਦਾਤਰ ਉਹ ਲਿਖਣਾ ਚਾਹੁੰਦੇ ਸਨ:
Identifier->Type = Question->Type;
Fragment N11: ਸ਼ੱਕੀ ਬਰੇਕ
void SystemZOperand::print(raw_ostream &OS) const {
switch (Kind) {
break;
case KindToken:
OS << "Token:" << getToken();
break;
case KindReg:
OS << "Reg:" << SystemZInstPrinter::getRegisterName(getReg());
break;
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਸ਼ੁਰੂ ਵਿੱਚ ਇੱਕ ਬਹੁਤ ਹੀ ਸ਼ੱਕੀ ਓਪਰੇਟਰ ਹੈ ਬ੍ਰੇਕ. ਕੀ ਤੁਸੀਂ ਇੱਥੇ ਕੁਝ ਹੋਰ ਲਿਖਣਾ ਭੁੱਲ ਗਏ ਹੋ?
ਫਰੈਗਮੈਂਟ N12: ਡੀਰੇਫਰੈਂਸਿੰਗ ਤੋਂ ਬਾਅਦ ਪੁਆਇੰਟਰ ਦੀ ਜਾਂਚ ਕਰਨਾ
InlineCost AMDGPUInliner::getInlineCost(CallSite CS) {
Function *Callee = CS.getCalledFunction();
Function *Caller = CS.getCaller();
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
if (!Callee || Callee->isDeclaration())
return llvm::InlineCost::getNever("undefined callee");
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਪੁਆਇੰਟਰ ਕੈਲੀ ਫੰਕਸ਼ਨ ਨੂੰ ਬੁਲਾਏ ਜਾਣ ਸਮੇਂ ਸ਼ੁਰੂ ਵਿੱਚ ਡੀਰੇਫਰੈਂਸ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਪ੍ਰਾਪਤ ਕਰੋ.
ਅਤੇ ਫਿਰ ਇਹ ਪਤਾ ਚਲਦਾ ਹੈ ਕਿ ਇਸ ਪੁਆਇੰਟਰ ਨੂੰ ਸਮਾਨਤਾ ਲਈ ਜਾਂਚਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ nullptr:
if (!Callee || Callee->isDeclaration())
ਪਰ ਬਹੁਤ ਦੇਰ ਹੋ ਚੁੱਕੀ ਹੈ...
ਫਰੈਗਮੈਂਟ N13 - N...: ਡੀਰੇਫਰੈਂਸਿੰਗ ਤੋਂ ਬਾਅਦ ਇੱਕ ਪੁਆਇੰਟਰ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ
ਪਿਛਲੇ ਕੋਡ ਦੇ ਟੁਕੜੇ ਵਿੱਚ ਚਰਚਾ ਕੀਤੀ ਗਈ ਸਥਿਤੀ ਵਿਲੱਖਣ ਨਹੀਂ ਹੈ. ਇਹ ਇੱਥੇ ਦਿਖਾਈ ਦਿੰਦਾ ਹੈ:
static Value *optimizeDoubleFP(CallInst *CI, IRBuilder<> &B,
bool isBinary, bool isPrecise = false) {
....
Function *CalleeFn = CI->getCalledFunction();
StringRef CalleeNm = CalleeFn->getName(); // <=
AttributeList CalleeAt = CalleeFn->getAttributes();
if (CalleeFn && !CalleeFn->isIntrinsic()) { // <=
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V595 [CWE-476] 'CalleeFn' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1079, 1081. SimplifyLibCalls.cpp 1079
ਅਤੇ ਇੱਥੇ:
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
LocalInstantiationScope *OuterMostScope) {
....
NamedDecl *ND = dyn_cast<NamedDecl>(New);
CXXRecordDecl *ThisContext =
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); // <=
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
ND && ND->isCXXInstanceMember()); // <=
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V595 [CWE-476] 'ND' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 532, 534. SemaTemplateInstantiateDecl.cpp 532
ਅਤੇ ਇੱਥੇ:
- V595 [CWE-476] 'U' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 404, 407. DWARFormValue.cpp 404
- V595 [CWE-476] 'ND' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 2149, 2151. SemaTemplateInstantiate.cpp 2149
ਅਤੇ ਫਿਰ ਮੈਂ V595 ਨੰਬਰ ਨਾਲ ਚੇਤਾਵਨੀਆਂ ਦਾ ਅਧਿਐਨ ਕਰਨ ਵਿੱਚ ਦਿਲਚਸਪੀ ਨਹੀਂ ਰੱਖਦਾ. ਇਸ ਲਈ ਮੈਨੂੰ ਨਹੀਂ ਪਤਾ ਕਿ ਇੱਥੇ ਸੂਚੀਬੱਧ ਕੀਤੇ ਗਏ ਲੋਕਾਂ ਤੋਂ ਇਲਾਵਾ ਹੋਰ ਸਮਾਨ ਗਲਤੀਆਂ ਹਨ ਜਾਂ ਨਹੀਂ। ਸਭ ਤੋਂ ਵੱਧ ਸੰਭਾਵਨਾ ਹੈ.
Fragment N17, N18: ਸ਼ੱਕੀ ਸ਼ਿਫਟ
static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize,
uint64_t &Encoding) {
....
unsigned Size = RegSize;
....
uint64_t NImms = ~(Size-1) << 1;
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਇਹ ਇੱਕ ਬੱਗ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ ਅਤੇ ਕੋਡ ਬਿਲਕੁਲ ਇਰਾਦੇ ਅਨੁਸਾਰ ਕੰਮ ਕਰਦਾ ਹੈ। ਪਰ ਇਹ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਇੱਕ ਬਹੁਤ ਹੀ ਸ਼ੱਕੀ ਜਗ੍ਹਾ ਹੈ ਅਤੇ ਇਸਦੀ ਜਾਂਚ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।
ਚਲੋ ਵੇਰੀਏਬਲ ਕਹੀਏ ਆਕਾਰ 16 ਦੇ ਬਰਾਬਰ ਹੈ, ਅਤੇ ਫਿਰ ਕੋਡ ਦੇ ਲੇਖਕ ਨੇ ਇਸਨੂੰ ਇੱਕ ਵੇਰੀਏਬਲ ਵਿੱਚ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਯੋਜਨਾ ਬਣਾਈ ਹੈ NImms ਮਤਲਬ:
1111111111111111111111111111111111111111111111111111111111100000
ਹਾਲਾਂਕਿ, ਅਸਲ ਵਿੱਚ ਨਤੀਜਾ ਇਹ ਹੋਵੇਗਾ:
0000000000000000000000000000000011111111111111111111111111100000
ਤੱਥ ਇਹ ਹੈ ਕਿ ਸਾਰੀਆਂ ਗਣਨਾਵਾਂ 32-ਬਿੱਟ ਅਣ-ਹਸਤਾਖਰਿਤ ਕਿਸਮ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਹੁੰਦੀਆਂ ਹਨ। ਅਤੇ ਕੇਵਲ ਤਦ ਹੀ, ਇਸ 32-ਬਿੱਟ ਅਣ-ਹਸਤਾਖਰਿਤ ਕਿਸਮ ਨੂੰ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਫੈਲਾਇਆ ਜਾਵੇਗਾ uint64_t. ਇਸ ਸਥਿਤੀ ਵਿੱਚ, ਸਭ ਤੋਂ ਮਹੱਤਵਪੂਰਨ ਬਿੱਟ ਜ਼ੀਰੋ ਹੋਣਗੇ।
ਤੁਸੀਂ ਇਸ ਤਰ੍ਹਾਂ ਸਥਿਤੀ ਨੂੰ ਠੀਕ ਕਰ ਸਕਦੇ ਹੋ:
uint64_t NImms = ~static_cast<uint64_t>(Size-1) << 1;
ਸਮਾਨ ਸਥਿਤੀ: V629 [CWE-190] 'Immr << 6' ਸਮੀਕਰਨ ਦਾ ਨਿਰੀਖਣ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। 32-ਬਿੱਟ ਕਿਸਮ ਦੇ ਬਾਅਦ ਦੇ ਵਿਸਥਾਰ ਦੇ ਨਾਲ 64-ਬਿੱਟ ਮੁੱਲ ਦਾ ਬਿੱਟ ਸ਼ਿਫਟ ਕਰਨਾ। AArch64AddressingModes.h 269
Fragment N19: ਗੁੰਮ ਕੀਵਰਡ ਹੋਰ?
void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
....
if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
// VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
// Skip it.
continue;
} if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { // <=
Op.addRegWithFPInputModsOperands(Inst, 2);
} else if (Op.isDPPCtrl()) {
Op.addImmOperands(Inst, 1);
} else if (Op.isImm()) {
// Handle optional arguments
OptionalIdx[Op.getImmTy()] = I;
} else {
llvm_unreachable("Invalid operand type");
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਇੱਥੇ ਕੋਈ ਗਲਤੀ ਨਹੀਂ ਹੈ। ਪਹਿਲੇ ਦੇ ਫਿਰ-ਬਲਾਕ ਤੋਂ ਲੈ ਕੇ if ਨਾਲ ਖਤਮ ਹੁੰਦਾ ਹੈ ਜਾਰੀ, ਫਿਰ ਕੋਈ ਫ਼ਰਕ ਨਹੀਂ ਪੈਂਦਾ, ਇੱਕ ਕੀਵਰਡ ਹੈ ਹੋਰ ਜਾਂ ਨਹੀਂ. ਕਿਸੇ ਵੀ ਤਰੀਕੇ ਨਾਲ ਕੋਡ ਇੱਕੋ ਜਿਹਾ ਕੰਮ ਕਰੇਗਾ। ਅਜੇ ਵੀ ਖੁੰਝ ਗਿਆ ਹੋਰ ਕੋਡ ਨੂੰ ਹੋਰ ਅਸਪਸ਼ਟ ਅਤੇ ਖਤਰਨਾਕ ਬਣਾਉਂਦਾ ਹੈ। ਜੇਕਰ ਭਵਿੱਖ ਵਿੱਚ ਜਾਰੀ ਗਾਇਬ ਹੋ ਜਾਂਦਾ ਹੈ, ਕੋਡ ਪੂਰੀ ਤਰ੍ਹਾਂ ਵੱਖਰੇ ਤਰੀਕੇ ਨਾਲ ਕੰਮ ਕਰਨਾ ਸ਼ੁਰੂ ਕਰ ਦੇਵੇਗਾ। ਮੇਰੇ ਵਿਚਾਰ ਵਿੱਚ ਇਸ ਨੂੰ ਸ਼ਾਮਿਲ ਕਰਨ ਲਈ ਬਿਹਤਰ ਹੈ ਹੋਰ.
ਫ੍ਰੈਗਮੈਂਟ N20: ਇੱਕੋ ਕਿਸਮ ਦੀਆਂ ਚਾਰ ਗਲਤੀਆਂ
LLVM_DUMP_METHOD void Symbol::dump(raw_ostream &OS) const {
std::string Result;
if (isUndefined())
Result += "(undef) ";
if (isWeakDefined())
Result += "(weak-def) ";
if (isWeakReferenced())
Result += "(weak-ref) ";
if (isThreadLocalValue())
Result += "(tlv) ";
switch (Kind) {
case SymbolKind::GlobalSymbol:
Result + Name.str(); // <=
break;
case SymbolKind::ObjectiveCClass:
Result + "(ObjC Class) " + Name.str(); // <=
break;
case SymbolKind::ObjectiveCClassEHType:
Result + "(ObjC Class EH) " + Name.str(); // <=
break;
case SymbolKind::ObjectiveCInstanceVariable:
Result + "(ObjC IVar) " + Name.str(); // <=
break;
}
OS << Result;
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀਆਂ:
- V655 [CWE-480] ਤਾਰਾਂ ਨੂੰ ਜੋੜਿਆ ਗਿਆ ਸੀ ਪਰ ਵਰਤਿਆ ਨਹੀਂ ਗਿਆ। 'ਨਤੀਜਾ + Name.str()' ਸਮੀਕਰਨ ਦੀ ਜਾਂਚ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। Symbol.cpp 32
- V655 [CWE-480] ਤਾਰਾਂ ਨੂੰ ਜੋੜਿਆ ਗਿਆ ਸੀ ਪਰ ਵਰਤਿਆ ਨਹੀਂ ਗਿਆ। 'ਨਤੀਜਾ + "(ObjC ਕਲਾਸ)" + Name.str()' ਸਮੀਕਰਨ ਦੀ ਜਾਂਚ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। Symbol.cpp 35
- V655 [CWE-480] ਤਾਰਾਂ ਨੂੰ ਜੋੜਿਆ ਗਿਆ ਸੀ ਪਰ ਵਰਤਿਆ ਨਹੀਂ ਗਿਆ। 'ਨਤੀਜਾ + "(ObjC ਕਲਾਸ EH) " + Name.str()' ਸਮੀਕਰਨ ਦੀ ਜਾਂਚ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। Symbol.cpp 38
- V655 [CWE-480] ਤਾਰਾਂ ਨੂੰ ਜੋੜਿਆ ਗਿਆ ਸੀ ਪਰ ਵਰਤਿਆ ਨਹੀਂ ਗਿਆ। 'ਨਤੀਜਾ + "(ObjC IVar)" + Name.str()' ਸਮੀਕਰਨ ਦੀ ਜਾਂਚ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। Symbol.cpp 41
ਦੁਰਘਟਨਾ ਦੁਆਰਾ, + = ਆਪਰੇਟਰ ਦੀ ਬਜਾਏ + ਆਪਰੇਟਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ। ਨਤੀਜਾ ਡਿਜ਼ਾਇਨ ਹੈ ਜੋ ਅਰਥ ਤੋਂ ਰਹਿਤ ਹਨ।
Fragment N21: ਪਰਿਭਾਸ਼ਿਤ ਵਿਵਹਾਰ
static void getReqFeatures(std::map<StringRef, int> &FeaturesMap,
const std::vector<Record *> &ReqFeatures) {
for (auto &R : ReqFeatures) {
StringRef AsmCondString = R->getValueAsString("AssemblerCondString");
SmallVector<StringRef, 4> Ops;
SplitString(AsmCondString, Ops, ",");
assert(!Ops.empty() && "AssemblerCondString cannot be empty");
for (auto &Op : Ops) {
assert(!Op.empty() && "Empty operator");
if (FeaturesMap.find(Op) == FeaturesMap.end())
FeaturesMap[Op] = FeaturesMap.size();
}
}
}
ਖਤਰਨਾਕ ਕੋਡ ਨੂੰ ਖੁਦ ਲੱਭਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ। ਅਤੇ ਇਹ ਧਿਆਨ ਭਟਕਾਉਣ ਲਈ ਇੱਕ ਤਸਵੀਰ ਹੈ ਤਾਂ ਜੋ ਜਵਾਬ ਨੂੰ ਤੁਰੰਤ ਨਾ ਦੇਖਿਆ ਜਾ ਸਕੇ:
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਸਮੱਸਿਆ ਲਾਈਨ:
FeaturesMap[Op] = FeaturesMap.size();
ਜੇਕਰ ਤੱਤ Op ਨਹੀਂ ਪਾਇਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਨਕਸ਼ੇ ਵਿੱਚ ਇੱਕ ਨਵਾਂ ਐਲੀਮੈਂਟ ਬਣਾਇਆ ਜਾਂਦਾ ਹੈ ਅਤੇ ਇਸ ਨਕਸ਼ੇ ਵਿੱਚ ਤੱਤਾਂ ਦੀ ਗਿਣਤੀ ਉੱਥੇ ਲਿਖੀ ਜਾਂਦੀ ਹੈ। ਇਹ ਸਿਰਫ਼ ਅਣਜਾਣ ਹੈ ਕਿ ਕੀ ਫੰਕਸ਼ਨ ਨੂੰ ਬੁਲਾਇਆ ਜਾਵੇਗਾ ਦਾ ਆਕਾਰ ਇੱਕ ਨਵਾਂ ਤੱਤ ਜੋੜਨ ਤੋਂ ਪਹਿਲਾਂ ਜਾਂ ਬਾਅਦ ਵਿੱਚ।
ਫ੍ਰੈਗਮੈਂਟ N22-N24: ਦੁਹਰਾਈਆਂ ਗਈਆਂ ਅਸਾਈਨਮੈਂਟਾਂ
Error MachOObjectFile::checkSymbolTable() const {
....
} else {
MachO::nlist STE = getSymbolTableEntry(SymDRI);
NType = STE.n_type; // <=
NType = STE.n_type; // <=
NSect = STE.n_sect;
NDesc = STE.n_desc;
NStrx = STE.n_strx;
NValue = STE.n_value;
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਮੈਨੂੰ ਨਹੀਂ ਲੱਗਦਾ ਕਿ ਇੱਥੇ ਕੋਈ ਅਸਲ ਗਲਤੀ ਹੈ। ਸਿਰਫ਼ ਇੱਕ ਬੇਲੋੜੀ ਦੁਹਰਾਈ ਗਈ ਅਸਾਈਨਮੈਂਟ। ਪਰ ਫਿਰ ਵੀ ਇੱਕ ਗਲਤੀ.
ਇਸੇ ਤਰ੍ਹਾਂ:
- V519 [CWE-563] 'B.NDesc' ਵੇਰੀਏਬਲ ਨੂੰ ਲਗਾਤਾਰ ਦੋ ਵਾਰ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਸ਼ਾਇਦ ਇਹ ਇੱਕ ਗਲਤੀ ਹੈ. ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1488, 1489. llvm-nm.cpp 1489
- V519 [CWE-563] ਵੇਰੀਏਬਲ ਨੂੰ ਲਗਾਤਾਰ ਦੋ ਵਾਰ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਸ਼ਾਇਦ ਇਹ ਇੱਕ ਗਲਤੀ ਹੈ. ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 59, 61. coff2yaml.cpp 61
Fragment N25-N27: ਹੋਰ ਪੁਨਰ-ਸਾਈਨਮੈਂਟ
ਹੁਣ ਆਉ ਦੁਬਾਰਾ ਅਸਾਈਨਮੈਂਟ ਦੇ ਥੋੜੇ ਵੱਖਰੇ ਸੰਸਕਰਣ ਨੂੰ ਵੇਖੀਏ.
bool Vectorizer::vectorizeLoadChain(
ArrayRef<Instruction *> Chain,
SmallPtrSet<Instruction *, 16> *InstructionsProcessed) {
....
unsigned Alignment = getAlignment(L0);
....
unsigned NewAlign = getOrEnforceKnownAlignment(L0->getPointerOperand(),
StackAdjustedAlignment,
DL, L0, nullptr, &DT);
if (NewAlign != 0)
Alignment = NewAlign;
Alignment = NewAlign;
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V519 [CWE-563] 'ਅਲਾਈਨਮੈਂਟ' ਵੇਰੀਏਬਲ ਨੂੰ ਲਗਾਤਾਰ ਦੋ ਵਾਰ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਸ਼ਾਇਦ ਇਹ ਇੱਕ ਗਲਤੀ ਹੈ. ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1158, 1160. LoadStoreVectorizer.cpp 1160
ਇਹ ਬਹੁਤ ਹੀ ਅਜੀਬ ਕੋਡ ਹੈ ਜਿਸ ਵਿੱਚ ਜ਼ਾਹਰ ਤੌਰ 'ਤੇ ਇੱਕ ਲਾਜ਼ੀਕਲ ਗਲਤੀ ਹੈ। ਸ਼ੁਰੂ ਵਿੱਚ, ਵੇਰੀਏਬਲ ਅਨੁਕੂਲਤਾ ਸਥਿਤੀ ਦੇ ਅਧਾਰ ਤੇ ਇੱਕ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਅਤੇ ਫਿਰ ਅਸਾਈਨਮੈਂਟ ਦੁਬਾਰਾ ਹੁੰਦੀ ਹੈ, ਪਰ ਹੁਣ ਬਿਨਾਂ ਕਿਸੇ ਜਾਂਚ ਦੇ.
ਸਮਾਨ ਸਥਿਤੀਆਂ ਇੱਥੇ ਵੇਖੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ:
- V519 [CWE-563] 'ਪ੍ਰਭਾਵ' ਵੇਰੀਏਬਲ ਨੂੰ ਲਗਾਤਾਰ ਦੋ ਵਾਰ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਸ਼ਾਇਦ ਇਹ ਇੱਕ ਗਲਤੀ ਹੈ. ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 152, 165. WebAssemblyRegStackify.cpp 165
- V519 [CWE-563] 'ExpectNoDerefChunk' ਵੇਰੀਏਬਲ ਨੂੰ ਲਗਾਤਾਰ ਦੋ ਵਾਰ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਸ਼ਾਇਦ ਇਹ ਇੱਕ ਗਲਤੀ ਹੈ. ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 4970, 4973. SemaType.cpp 4973
Fragment N28: ਹਮੇਸ਼ਾ ਸਹੀ ਸਥਿਤੀ
static int readPrefixes(struct InternalInstruction* insn) {
....
uint8_t byte = 0;
uint8_t nextByte;
....
if (byte == 0xf3 && (nextByte == 0x88 || nextByte == 0x89 ||
nextByte == 0xc6 || nextByte == 0xc7)) {
insn->xAcquireRelease = true;
if (nextByte != 0x90) // PAUSE instruction support // <=
break;
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਜਾਂਚ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ। ਵੇਰੀਏਬਲ nextByte ਹਮੇਸ਼ਾ ਮੁੱਲ ਦੇ ਬਰਾਬਰ ਨਹੀਂ ਹੁੰਦਾ 0x90, ਜੋ ਕਿ ਪਿਛਲੀ ਜਾਂਚ ਤੋਂ ਬਾਅਦ ਹੈ। ਇਹ ਕਿਸੇ ਤਰ੍ਹਾਂ ਦੀ ਲਾਜ਼ੀਕਲ ਗਲਤੀ ਹੈ।
Fragment N29 - N...: ਹਮੇਸ਼ਾ ਸਹੀ/ਗਲਤ ਸਥਿਤੀਆਂ
ਵਿਸ਼ਲੇਸ਼ਕ ਬਹੁਤ ਸਾਰੀਆਂ ਚੇਤਾਵਨੀਆਂ ਜਾਰੀ ਕਰਦਾ ਹੈ ਕਿ ਸਾਰੀ ਸਥਿਤੀ (
static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
if (RegNo > 13)
return MCDisassembler::Fail;
if ((RegNo & 1) || RegNo == 0xe)
S = MCDisassembler::SoftFail;
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਸਥਿਰ 0xE ਦਸ਼ਮਲਵ ਵਿੱਚ ਮੁੱਲ 14 ਹੈ। ਇਮਤਿਹਾਨ RegNo == 0xe ਇਸ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ ਕਿਉਂਕਿ ਜੇ RegNo > 13, ਫਿਰ ਫੰਕਸ਼ਨ ਆਪਣਾ ਐਗਜ਼ੀਕਿਊਸ਼ਨ ਪੂਰਾ ਕਰੇਗਾ।
IDs V547 ਅਤੇ V560 ਦੇ ਨਾਲ ਕਈ ਹੋਰ ਚੇਤਾਵਨੀਆਂ ਸਨ, ਪਰ ਜਿਵੇਂ ਕਿ
ਮੈਂ ਤੁਹਾਨੂੰ ਇੱਕ ਉਦਾਹਰਣ ਦੇਵਾਂਗਾ ਕਿ ਇਹਨਾਂ ਟਰਿਗਰਾਂ ਦਾ ਅਧਿਐਨ ਕਰਨਾ ਬੋਰਿੰਗ ਕਿਉਂ ਹੈ. ਵਿਸ਼ਲੇਸ਼ਕ ਹੇਠਾਂ ਦਿੱਤੇ ਕੋਡ ਲਈ ਚੇਤਾਵਨੀ ਜਾਰੀ ਕਰਨ ਵਿੱਚ ਬਿਲਕੁਲ ਸਹੀ ਹੈ। ਪਰ ਇਹ ਕੋਈ ਗਲਤੀ ਨਹੀਂ ਹੈ।
bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons,
tok::TokenKind ClosingBraceKind) {
bool HasError = false;
....
HasError = true;
if (!ContinueOnSemicolons)
return !HasError;
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V547 [CWE-570] ਸਮੀਕਰਨ '!HasError' ਹਮੇਸ਼ਾ ਗਲਤ ਹੁੰਦਾ ਹੈ। UnwrappedLineParser.cpp 1635
Fragment N30: ਸ਼ੱਕੀ ਵਾਪਸੀ
static bool
isImplicitlyDef(MachineRegisterInfo &MRI, unsigned Reg) {
for (MachineRegisterInfo::def_instr_iterator It = MRI.def_instr_begin(Reg),
E = MRI.def_instr_end(); It != E; ++It) {
return (*It).isImplicitDef();
}
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਇਹ ਜਾਂ ਤਾਂ ਇੱਕ ਗਲਤੀ ਹੈ ਜਾਂ ਇੱਕ ਖਾਸ ਤਕਨੀਕ ਹੈ ਜਿਸਦਾ ਉਦੇਸ਼ ਕੋਡ ਨੂੰ ਪੜ੍ਹਨ ਵਾਲੇ ਪ੍ਰੋਗਰਾਮਰਾਂ ਨੂੰ ਕੁਝ ਸਮਝਾਉਣਾ ਹੈ। ਇਹ ਡਿਜ਼ਾਈਨ ਮੈਨੂੰ ਕੁਝ ਨਹੀਂ ਸਮਝਾਉਂਦਾ ਅਤੇ ਬਹੁਤ ਸ਼ੱਕੀ ਲੱਗਦਾ ਹੈ। ਇਸ ਤਰ੍ਹਾਂ ਨਾ ਲਿਖਣਾ ਬਿਹਤਰ ਹੈ :)।
ਥੱਕ ਗਏ? ਫਿਰ ਚਾਹ ਜਾਂ ਕੌਫੀ ਬਣਾਉਣ ਦਾ ਸਮਾਂ ਆ ਗਿਆ।
ਨਵੇਂ ਡਾਇਗਨੌਸਟਿਕਸ ਦੁਆਰਾ ਪਛਾਣੇ ਗਏ ਨੁਕਸ
ਮੈਨੂੰ ਲਗਦਾ ਹੈ ਕਿ ਪੁਰਾਣੇ ਡਾਇਗਨੌਸਟਿਕਸ ਦੀਆਂ 30 ਸਰਗਰਮੀਆਂ ਕਾਫ਼ੀ ਹਨ. ਆਓ ਹੁਣ ਦੇਖਦੇ ਹਾਂ ਕਿ ਨਵੇਂ ਡਾਇਗਨੌਸਟਿਕਸ ਨਾਲ ਕਿਹੜੀਆਂ ਦਿਲਚਸਪ ਚੀਜ਼ਾਂ ਲੱਭੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ ਜੋ ਬਾਅਦ ਵਿੱਚ ਵਿਸ਼ਲੇਸ਼ਕ ਵਿੱਚ ਪ੍ਰਗਟ ਹੋਈਆਂ
Fragment N31: ਪਹੁੰਚਯੋਗ ਕੋਡ
Error CtorDtorRunner::run() {
....
if (auto CtorDtorMap =
ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names),
NoDependenciesToRegister, true))
{
....
return Error::success();
} else
return CtorDtorMap.takeError();
CtorDtorsByPriority.clear();
return Error::success();
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਜਿਵੇਂ ਕਿ ਤੁਸੀਂ ਦੇਖ ਸਕਦੇ ਹੋ, ਆਪਰੇਟਰ ਦੀਆਂ ਦੋਵੇਂ ਸ਼ਾਖਾਵਾਂ if ਆਪਰੇਟਰ ਨੂੰ ਇੱਕ ਕਾਲ ਨਾਲ ਖਤਮ ਹੁੰਦਾ ਹੈ ਵਾਪਸੀ. ਇਸ ਅਨੁਸਾਰ, ਕੰਟੇਨਰ CtorDtorsByPriority ਕਦੇ ਵੀ ਸਾਫ਼ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।
Fragment N32: ਪਹੁੰਚਯੋਗ ਕੋਡ
bool LLParser::ParseSummaryEntry() {
....
switch (Lex.getKind()) {
case lltok::kw_gv:
return ParseGVEntry(SummaryID);
case lltok::kw_module:
return ParseModuleEntry(SummaryID);
case lltok::kw_typeid:
return ParseTypeIdEntry(SummaryID); // <=
break; // <=
default:
return Error(Lex.getLoc(), "unexpected summary kind");
}
Lex.setIgnoreColonInIdentifiers(false); // <=
return false;
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V779 [CWE-561] ਪਹੁੰਚਯੋਗ ਕੋਡ ਖੋਜਿਆ ਗਿਆ। ਇਹ ਸੰਭਵ ਹੈ ਕਿ ਕੋਈ ਗਲਤੀ ਮੌਜੂਦ ਹੈ। LLParser.cpp 835
ਦਿਲਚਸਪ ਸਥਿਤੀ. ਆਓ ਪਹਿਲਾਂ ਇਸ ਸਥਾਨ ਨੂੰ ਵੇਖੀਏ:
return ParseTypeIdEntry(SummaryID);
break;
ਪਹਿਲੀ ਨਜ਼ਰ 'ਤੇ, ਅਜਿਹਾ ਲਗਦਾ ਹੈ ਕਿ ਇੱਥੇ ਕੋਈ ਗਲਤੀ ਨਹੀਂ ਹੈ. ਇਹ ਆਪਰੇਟਰ ਵਰਗਾ ਦਿਸਦਾ ਹੈ ਬ੍ਰੇਕ ਇੱਥੇ ਇੱਕ ਵਾਧੂ ਹੈ, ਅਤੇ ਤੁਸੀਂ ਇਸਨੂੰ ਸਿਰਫ਼ ਮਿਟਾ ਸਕਦੇ ਹੋ। ਹਾਲਾਂਕਿ, ਸਾਰੇ ਇੰਨੇ ਸਧਾਰਨ ਨਹੀਂ ਹਨ.
ਵਿਸ਼ਲੇਸ਼ਕ ਲਾਈਨਾਂ 'ਤੇ ਇੱਕ ਚੇਤਾਵਨੀ ਜਾਰੀ ਕਰਦਾ ਹੈ:
Lex.setIgnoreColonInIdentifiers(false);
return false;
ਅਤੇ ਵਾਸਤਵ ਵਿੱਚ, ਇਹ ਕੋਡ ਪਹੁੰਚਯੋਗ ਨਹੀਂ ਹੈ। ਵਿਚ ਸਾਰੇ ਮਾਮਲੇ ਸਵਿੱਚ ਆਪਰੇਟਰ ਦੀ ਇੱਕ ਕਾਲ ਨਾਲ ਖਤਮ ਹੁੰਦਾ ਹੈ ਵਾਪਸੀ. ਅਤੇ ਹੁਣ ਇਕੱਲੇ ਬੇਸਮਝ ਬ੍ਰੇਕ ਇੰਨਾ ਨੁਕਸਾਨਦੇਹ ਨਹੀਂ ਲੱਗਦਾ! ਸ਼ਾਇਦ ਇੱਕ ਸ਼ਾਖਾ ਦੇ ਨਾਲ ਖਤਮ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ ਬ੍ਰੇਕ, ਨਹੀਂ ਵਾਪਸੀ?
Fragment N33: ਉੱਚ ਬਿੱਟਾਂ ਦਾ ਬੇਤਰਤੀਬ ਰੀਸੈਟ
unsigned getStubAlignment() override {
if (Arch == Triple::systemz)
return 8;
else
return 1;
}
Expected<unsigned>
RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
const SectionRef &Section,
bool IsCode) {
....
uint64_t DataSize = Section.getSize();
....
if (StubBufSize > 0)
DataSize &= ~(getStubAlignment() - 1);
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਕਿਰਪਾ ਕਰਕੇ ਧਿਆਨ ਦਿਓ ਕਿ ਫੰਕਸ਼ਨ getStubAlignment ਵਾਪਸੀ ਦੀ ਕਿਸਮ ਦਸਤਖਤ ਕੀਤੇ. ਆਉ ਸਮੀਕਰਨ ਦੇ ਮੁੱਲ ਦੀ ਗਣਨਾ ਕਰੀਏ, ਇਹ ਮੰਨਦੇ ਹੋਏ ਕਿ ਫੰਕਸ਼ਨ ਮੁੱਲ 8 ਦਿੰਦਾ ਹੈ:
~(getStubAlignment() - 1)
~(8u-1)
0xFFFFFFFF8u
ਹੁਣ ਧਿਆਨ ਦਿਓ ਕਿ ਵੇਰੀਏਬਲ ਡਾਟਾ ਆਕਾਰ ਇੱਕ 64-ਬਿੱਟ ਅਣ-ਹਸਤਾਖਰਿਤ ਕਿਸਮ ਹੈ। ਇਹ ਪਤਾ ਚਲਦਾ ਹੈ ਕਿ ਜਦੋਂ DataSize & 0xFFFFFFF8u ਓਪਰੇਸ਼ਨ ਕਰਦੇ ਹੋ, ਤਾਂ ਸਾਰੇ 0 ਉੱਚ-ਆਰਡਰ ਬਿੱਟ ਜ਼ੀਰੋ 'ਤੇ ਰੀਸੈਟ ਕੀਤੇ ਜਾਣਗੇ। ਜ਼ਿਆਦਾਤਰ ਸੰਭਾਵਨਾ ਹੈ, ਇਹ ਉਹ ਨਹੀਂ ਹੈ ਜੋ ਪ੍ਰੋਗਰਾਮਰ ਚਾਹੁੰਦਾ ਸੀ. ਮੈਨੂੰ ਸ਼ੱਕ ਹੈ ਕਿ ਉਹ ਗਣਨਾ ਕਰਨਾ ਚਾਹੁੰਦਾ ਸੀ: DataSize & 8xFFFFFFFFFFFFFFXNUMXu.
ਗਲਤੀ ਨੂੰ ਠੀਕ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਇਹ ਲਿਖਣਾ ਚਾਹੀਦਾ ਹੈ:
DataSize &= ~(static_cast<uint64_t>(getStubAlignment()) - 1);
ਜਾਂ ਇਸ ਤਰ੍ਹਾਂ:
DataSize &= ~(getStubAlignment() - 1ULL);
Fragment N34: ਅਸਫ਼ਲ ਸਪਸ਼ਟ ਕਿਸਮ ਕਾਸਟ
template <typename T>
void scaleShuffleMask(int Scale, ArrayRef<T> Mask,
SmallVectorImpl<T> &ScaledMask) {
assert(0 < Scale && "Unexpected scaling factor");
int NumElts = Mask.size();
ScaledMask.assign(static_cast<size_t>(NumElts * Scale), -1);
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਟਾਈਪ ਵੇਰੀਏਬਲ ਨੂੰ ਗੁਣਾ ਕਰਨ ਵੇਲੇ ਓਵਰਫਲੋ ਤੋਂ ਬਚਣ ਲਈ ਸਪੱਸ਼ਟ ਕਿਸਮ ਦੀ ਕਾਸਟਿੰਗ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਇੰਟ. ਹਾਲਾਂਕਿ, ਇੱਥੇ ਸਪਸ਼ਟ ਕਿਸਮ ਦੀ ਕਾਸਟਿੰਗ ਓਵਰਫਲੋ ਤੋਂ ਸੁਰੱਖਿਆ ਨਹੀਂ ਕਰਦੀ ਹੈ। ਪਹਿਲਾਂ, ਵੇਰੀਏਬਲ ਨੂੰ ਗੁਣਾ ਕੀਤਾ ਜਾਵੇਗਾ, ਅਤੇ ਕੇਵਲ ਤਦ ਹੀ ਗੁਣਾ ਦੇ 32-ਬਿੱਟ ਨਤੀਜੇ ਨੂੰ ਕਿਸਮ ਤੱਕ ਫੈਲਾਇਆ ਜਾਵੇਗਾ
Fragment N35: ਅਸਫਲ ਕਾਪੀ-ਪੇਸਟ
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
....
if (!match(Op0, m_PosZeroFP()) && isKnownNeverNaN(Op0, &TLI)) {
I.setOperand(0, ConstantFP::getNullValue(Op0->getType()));
return &I;
}
if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
I.setOperand(1, ConstantFP::getNullValue(Op0->getType())); // <=
return &I;
}
....
}
ਇਹ ਨਵਾਂ ਦਿਲਚਸਪ ਡਾਇਗਨੌਸਟਿਕ ਉਹਨਾਂ ਸਥਿਤੀਆਂ ਦੀ ਪਛਾਣ ਕਰਦਾ ਹੈ ਜਿੱਥੇ ਕੋਡ ਦੇ ਇੱਕ ਟੁਕੜੇ ਦੀ ਨਕਲ ਕੀਤੀ ਗਈ ਹੈ ਅਤੇ ਇਸ ਵਿੱਚ ਕੁਝ ਨਾਮ ਬਦਲੇ ਜਾਣੇ ਸ਼ੁਰੂ ਹੋ ਗਏ ਹਨ, ਪਰ ਇੱਕ ਥਾਂ ਤੇ ਉਹਨਾਂ ਨੇ ਇਸਨੂੰ ਠੀਕ ਨਹੀਂ ਕੀਤਾ ਹੈ।
ਕਿਰਪਾ ਕਰਕੇ ਧਿਆਨ ਦਿਓ ਕਿ ਦੂਜੇ ਬਲਾਕ ਵਿੱਚ ਉਹ ਬਦਲ ਗਏ ਹਨ Op0 'ਤੇ Op1. ਪਰ ਇੱਕ ਥਾਂ ਤੇ ਉਹਨਾਂ ਨੇ ਇਸਨੂੰ ਠੀਕ ਨਹੀਂ ਕੀਤਾ। ਸੰਭਾਵਤ ਤੌਰ 'ਤੇ ਇਹ ਇਸ ਤਰ੍ਹਾਂ ਲਿਖਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਸੀ:
if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
I.setOperand(1, ConstantFP::getNullValue(Op1->getType()));
return &I;
}
Fragment N36: ਪਰਿਵਰਤਨਸ਼ੀਲ ਉਲਝਣ
struct Status {
unsigned Mask;
unsigned Mode;
Status() : Mask(0), Mode(0){};
Status(unsigned Mask, unsigned Mode) : Mask(Mask), Mode(Mode) {
Mode &= Mask;
};
....
};
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਫੰਕਸ਼ਨ ਆਰਗੂਮੈਂਟਾਂ ਨੂੰ ਕਲਾਸ ਮੈਂਬਰਾਂ ਦੇ ਸਮਾਨ ਨਾਮ ਦੇਣਾ ਬਹੁਤ ਖਤਰਨਾਕ ਹੈ। ਇਹ ਉਲਝਣ ਵਿੱਚ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ ਬਹੁਤ ਹੀ ਆਸਾਨ ਹੈ. ਸਾਡੇ ਸਾਹਮਣੇ ਅਜਿਹਾ ਹੀ ਮਾਮਲਾ ਹੈ। ਇਹ ਸਮੀਕਰਨ ਅਰਥ ਨਹੀਂ ਰੱਖਦਾ:
Mode &= Mask;
ਫੰਕਸ਼ਨ ਆਰਗੂਮੈਂਟ ਬਦਲਦਾ ਹੈ। ਇਹ ਸਭ ਹੈ. ਇਹ ਦਲੀਲ ਹੁਣ ਵਰਤੀ ਨਹੀਂ ਜਾਂਦੀ। ਜ਼ਿਆਦਾਤਰ ਸੰਭਾਵਨਾ ਹੈ ਕਿ ਤੁਹਾਨੂੰ ਇਸ ਨੂੰ ਇਸ ਤਰ੍ਹਾਂ ਲਿਖਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਸੀ:
Status(unsigned Mask, unsigned Mode) : Mask(Mask), Mode(Mode) {
this->Mode &= Mask;
};
Fragment N37: ਪਰਿਵਰਤਨਸ਼ੀਲ ਉਲਝਣ
class SectionBase {
....
uint64_t Size = 0;
....
};
class SymbolTableSection : public SectionBase {
....
};
void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
SectionBase *DefinedIn, uint64_t Value,
uint8_t Visibility, uint16_t Shndx,
uint64_t Size) {
....
Sym.Value = Value;
Sym.Visibility = Visibility;
Sym.Size = Size;
Sym.Index = Symbols.size();
Symbols.emplace_back(llvm::make_unique<Symbol>(Sym));
Size += this->EntrySize;
}
ਚੇਤਾਵਨੀ PVS-ਸਟੂਡੀਓ: V1001 [CWE-563] 'ਸਾਈਜ਼' ਵੇਰੀਏਬਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਪਰ ਫੰਕਸ਼ਨ ਦੇ ਅੰਤ ਤੱਕ ਵਰਤਿਆ ਨਹੀਂ ਜਾਂਦਾ ਹੈ। Object.cpp 424
ਸਥਿਤੀ ਪਹਿਲਾਂ ਵਰਗੀ ਹੈ। ਇਹ ਲਿਖਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ:
this->Size += this->EntrySize;
Fragment N38-N47: ਉਹ ਸੂਚਕਾਂਕ ਦੀ ਜਾਂਚ ਕਰਨਾ ਭੁੱਲ ਗਏ
ਪਹਿਲਾਂ, ਅਸੀਂ ਡਾਇਗਨੌਸਟਿਕ ਟਰਿਗਰਿੰਗ ਦੀਆਂ ਉਦਾਹਰਣਾਂ ਨੂੰ ਦੇਖਿਆ ਸੀ
int getGEPCost(Type *PointeeType, const Value *Ptr,
ArrayRef<const Value *> Operands) {
....
if (Ptr != nullptr) { // <=
assert(....);
BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts());
}
bool HasBaseReg = (BaseGV == nullptr);
auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType()); // <=
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V1004 [CWE-476] 'Ptr' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਤਸਦੀਕ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 729, 738. TargetTransformInfoImpl.h 738
ਪਰਿਵਰਤਨਸ਼ੀਲ ਪੀ.ਟੀ.ਆਰ ਬਰਾਬਰ ਹੋ ਸਕਦਾ ਹੈ nullptr, ਜਿਵੇਂ ਕਿ ਜਾਂਚ ਦੁਆਰਾ ਪ੍ਰਮਾਣਿਤ ਹੈ:
if (Ptr != nullptr)
ਹਾਲਾਂਕਿ, ਇਸ ਪੁਆਇੰਟਰ ਦੇ ਹੇਠਾਂ ਮੁੱਢਲੀ ਜਾਂਚ ਦੇ ਬਿਨਾਂ ਹਵਾਲਾ ਦਿੱਤਾ ਗਿਆ ਹੈ:
auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType());
ਆਓ ਇਸੇ ਤਰ੍ਹਾਂ ਦੇ ਇਕ ਹੋਰ ਮਾਮਲੇ 'ਤੇ ਗੌਰ ਕਰੀਏ।
llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD,
bool Stub) {
....
auto *FD = dyn_cast<FunctionDecl>(GD.getDecl());
SmallVector<QualType, 16> ArgTypes;
if (FD) // <=
for (const ParmVarDecl *Parm : FD->parameters())
ArgTypes.push_back(Parm->getType());
CallingConv CC = FD->getType()->castAs<FunctionType>()->getCallConv(); // <=
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V1004 [CWE-476] 'FD' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 3228, 3231. CGDebugInfo.cpp 3231
ਚਿੰਨ੍ਹ ਵੱਲ ਧਿਆਨ ਦਿਓ FD. ਮੈਨੂੰ ਯਕੀਨ ਹੈ ਕਿ ਸਮੱਸਿਆ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਦਿਖਾਈ ਦੇ ਰਹੀ ਹੈ ਅਤੇ ਕਿਸੇ ਵਿਸ਼ੇਸ਼ ਵਿਆਖਿਆ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।
ਅਤੇ ਅੱਗੇ:
static void computePolynomialFromPointer(Value &Ptr, Polynomial &Result,
Value *&BasePtr,
const DataLayout &DL) {
PointerType *PtrTy = dyn_cast<PointerType>(Ptr.getType());
if (!PtrTy) { // <=
Result = Polynomial();
BasePtr = nullptr;
}
unsigned PointerBits =
DL.getIndexSizeInBits(PtrTy->getPointerAddressSpace()); // <=
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V1004 [CWE-476] 'PtrTy' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 960, 965. InterleavedLoadCombinePass.cpp 965
ਅਜਿਹੀਆਂ ਗਲਤੀਆਂ ਤੋਂ ਆਪਣੇ ਆਪ ਨੂੰ ਕਿਵੇਂ ਬਚਾਇਆ ਜਾਵੇ? ਕੋਡ-ਸਮੀਖਿਆ 'ਤੇ ਵਧੇਰੇ ਧਿਆਨ ਰੱਖੋ ਅਤੇ ਨਿਯਮਿਤ ਤੌਰ 'ਤੇ ਆਪਣੇ ਕੋਡ ਦੀ ਜਾਂਚ ਕਰਨ ਲਈ PVS-ਸਟੂਡੀਓ ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰੋ।
ਇਸ ਕਿਸਮ ਦੀਆਂ ਗਲਤੀਆਂ ਵਾਲੇ ਹੋਰ ਕੋਡ ਦੇ ਟੁਕੜਿਆਂ ਦਾ ਹਵਾਲਾ ਦੇਣ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ। ਮੈਂ ਲੇਖ ਵਿੱਚ ਸਿਰਫ ਚੇਤਾਵਨੀਆਂ ਦੀ ਇੱਕ ਸੂਚੀ ਛੱਡਾਂਗਾ:
- V1004 [CWE-476] 'Expr' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1049, 1078. DebugInfoMetadata.cpp 1078
- V1004 [CWE-476] 'PI' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 733, 753. LegacyPassManager.cpp 753
- V1004 [CWE-476] 'StatepointCall' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 4371, 4379. Verifier.cpp 4379
- V1004 [CWE-476] 'RV' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 2263, 2268. TGParser.cpp 2268
- V1004 [CWE-476] 'CalleeFn' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1081, 1096. SimplifyLibCalls.cpp 1096
- V1004 [CWE-476] 'TC' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ ਅਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1819, 1824. ਡਰਾਈਵਰ ਸੀਪੀਪੀ 1824
Fragment N48-N60: ਨਾਜ਼ੁਕ ਨਹੀਂ, ਪਰ ਇੱਕ ਨੁਕਸ (ਸੰਭਵ ਮੈਮੋਰੀ ਲੀਕ)
std::unique_ptr<IRMutator> createISelMutator() {
....
std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
Strategies.emplace_back(
new InjectorIRStrategy(InjectorIRStrategy::getDefaultOps()));
....
}
PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ:
ਵਰਗੇ ਇੱਕ ਕੰਟੇਨਰ ਦੇ ਅੰਤ ਵਿੱਚ ਇੱਕ ਤੱਤ ਸ਼ਾਮਿਲ ਕਰਨ ਲਈ std::vector > ਤੁਸੀਂ ਸਿਰਫ਼ ਲਿਖ ਨਹੀਂ ਸਕਦੇ xxx.push_back(ਨਵਾਂ X), ਕਿਉਂਕਿ ਇੱਥੇ ਕੋਈ ਅਪ੍ਰਤੱਖ ਰੂਪਾਂਤਰਨ ਨਹੀਂ ਹੈ X* в std::unique_ptr.
ਇੱਕ ਸਾਂਝਾ ਹੱਲ ਲਿਖਣਾ ਹੈ xxx.emplace_back(ਨਵਾਂ X)ਕਿਉਂਕਿ ਇਹ ਕੰਪਾਇਲ ਕਰਦਾ ਹੈ: method emplace_back ਕਿਸੇ ਤੱਤ ਨੂੰ ਇਸਦੇ ਆਰਗੂਮੈਂਟਸ ਤੋਂ ਸਿੱਧਾ ਬਣਾਉਂਦਾ ਹੈ ਅਤੇ ਇਸਲਈ ਸਪਸ਼ਟ ਕੰਸਟਰਕਟਰ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦਾ ਹੈ।
ਇਹ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹੈ। ਜੇਕਰ ਵੈਕਟਰ ਭਰਿਆ ਹੋਇਆ ਹੈ, ਤਾਂ ਮੈਮੋਰੀ ਮੁੜ-ਅਲਾਟ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਮੈਮੋਰੀ ਰੀ-ਲੋਕੇਸ਼ਨ ਓਪਰੇਸ਼ਨ ਫੇਲ ਹੋ ਸਕਦਾ ਹੈ, ਨਤੀਜੇ ਵਜੋਂ ਇੱਕ ਅਪਵਾਦ ਸੁੱਟਿਆ ਜਾ ਰਿਹਾ ਹੈ std::bad_alloc. ਇਸ ਸਥਿਤੀ ਵਿੱਚ, ਪੁਆਇੰਟਰ ਖਤਮ ਹੋ ਜਾਵੇਗਾ ਅਤੇ ਬਣਾਈ ਗਈ ਵਸਤੂ ਨੂੰ ਕਦੇ ਵੀ ਮਿਟਾਇਆ ਨਹੀਂ ਜਾਵੇਗਾ।
ਇੱਕ ਸੁਰੱਖਿਅਤ ਹੱਲ ਬਣਾਉਣਾ ਹੈ ਵਿਲੱਖਣ_ptrਜੋ ਕਿ ਵੈਕਟਰ ਦੁਆਰਾ ਮੈਮੋਰੀ ਨੂੰ ਮੁੜ ਨਿਰਧਾਰਤ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪੁਆਇੰਟਰ ਦਾ ਮਾਲਕ ਹੋਵੇਗਾ:
xxx.push_back(std::unique_ptr<X>(new X))
C++ 14 ਤੋਂ, ਤੁਸੀਂ 'std::make_unique' ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹੋ:
xxx.push_back(std::make_unique<X>())
LLVM ਲਈ ਇਸ ਕਿਸਮ ਦਾ ਨੁਕਸ ਨਾਜ਼ੁਕ ਨਹੀਂ ਹੈ। ਜੇਕਰ ਮੈਮੋਰੀ ਨਿਰਧਾਰਤ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ, ਤਾਂ ਕੰਪਾਈਲਰ ਬਸ ਬੰਦ ਹੋ ਜਾਵੇਗਾ। ਹਾਲਾਂਕਿ, ਲੰਬੇ ਨਾਲ ਐਪਲੀਕੇਸ਼ਨਾਂ ਲਈ
ਇਸ ਲਈ, ਹਾਲਾਂਕਿ ਇਹ ਕੋਡ LLVM ਲਈ ਕੋਈ ਵਿਹਾਰਕ ਖ਼ਤਰਾ ਨਹੀਂ ਬਣਾਉਂਦਾ, ਮੈਨੂੰ ਇਸ ਗਲਤੀ ਪੈਟਰਨ ਬਾਰੇ ਗੱਲ ਕਰਨਾ ਲਾਭਦਾਇਕ ਲੱਗਿਆ ਅਤੇ ਇਹ ਕਿ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਨੇ ਇਸਦੀ ਪਛਾਣ ਕਰਨਾ ਸਿੱਖ ਲਿਆ ਹੈ।
ਇਸ ਕਿਸਮ ਦੀਆਂ ਹੋਰ ਚੇਤਾਵਨੀਆਂ:
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਪਾਸ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. PassManager.h 546
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'AAs' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. ਉਪਨਾਮ ਵਿਸ਼ਲੇਸ਼ਣ.h 324
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਐਂਟਰੀਆਂ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. DWARFDebugFrame.cpp 519
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'AllEdges' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. CFGMST.h 268
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'VMaps' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. SimpleLoopUnswitch.cpp 2012
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਰਿਕਾਰਡ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. FDRLogBuilder.h 30
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'PendingSubmodules' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. ModuleMap.cpp 810
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਆਬਜੈਕਟਸ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. DebugMap.cpp 88
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਰਣਨੀਤੀਆਂ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-isel-fuzzer.cpp 60
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 685
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 686
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 688
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 689
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 690
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 691
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 692
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 693
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਮੋਡੀਫਾਇਰ' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-stress.cpp 694
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'Operands' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. GlobalISelEmitter.cpp 1911
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਸਟੈਸ਼' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. GlobalISelEmitter.cpp 2100
- V1023 [CWE-460] 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'Matchers' ਕੰਟੇਨਰ ਵਿੱਚ ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. GlobalISelEmitter.cpp 2702
ਸਿੱਟਾ
ਮੈਂ ਕੁੱਲ ਮਿਲਾ ਕੇ 60 ਚੇਤਾਵਨੀਆਂ ਜਾਰੀ ਕੀਤੀਆਂ ਅਤੇ ਫਿਰ ਬੰਦ ਕਰ ਦਿੱਤੀਆਂ। ਕੀ ਕੋਈ ਹੋਰ ਨੁਕਸ ਹਨ ਜੋ PVS-ਸਟੂਡੀਓ ਐਨਾਲਾਈਜ਼ਰ LLVM ਵਿੱਚ ਖੋਜਦਾ ਹੈ? ਹਾਂ ਮੇਰੇ ਕੋਲ ਹੈ. ਹਾਲਾਂਕਿ, ਜਦੋਂ ਮੈਂ ਲੇਖ ਲਈ ਕੋਡ ਦੇ ਟੁਕੜੇ ਲਿਖ ਰਿਹਾ ਸੀ, ਇਹ ਦੇਰ ਸ਼ਾਮ ਸੀ, ਜਾਂ ਰਾਤ ਵੀ, ਅਤੇ ਮੈਂ ਫੈਸਲਾ ਕੀਤਾ ਕਿ ਇਹ ਇੱਕ ਦਿਨ ਕਾਲ ਕਰਨ ਦਾ ਸਮਾਂ ਸੀ।
ਮੈਨੂੰ ਉਮੀਦ ਹੈ ਕਿ ਤੁਹਾਨੂੰ ਇਹ ਦਿਲਚਸਪ ਲੱਗਿਆ ਹੈ ਅਤੇ ਤੁਸੀਂ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਨੂੰ ਅਜ਼ਮਾਉਣਾ ਚਾਹੋਗੇ।
ਤੁਸੀਂ ਐਨਾਲਾਈਜ਼ਰ ਨੂੰ ਡਾਉਨਲੋਡ ਕਰ ਸਕਦੇ ਹੋ ਅਤੇ ਮਾਈਨਸਵੀਪਰ ਕੁੰਜੀ ਨੂੰ ਇੱਥੇ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ
ਸਭ ਤੋਂ ਮਹੱਤਵਪੂਰਨ, ਨਿਯਮਿਤ ਤੌਰ 'ਤੇ ਸਥਿਰ ਵਿਸ਼ਲੇਸ਼ਣ ਦੀ ਵਰਤੋਂ ਕਰੋ। ਇੱਕ ਵਾਰ ਦੀ ਜਾਂਚ, ਸਥਿਰ ਵਿਸ਼ਲੇਸ਼ਣ ਅਤੇ PVS-ਸਟੂਡੀਓ ਦੀ ਕਾਰਜਪ੍ਰਣਾਲੀ ਨੂੰ ਪ੍ਰਸਿੱਧ ਬਣਾਉਣ ਲਈ ਸਾਡੇ ਦੁਆਰਾ ਕੀਤੇ ਗਏ ਇੱਕ ਆਮ ਦ੍ਰਿਸ਼ ਨਹੀਂ ਹਨ।
ਤੁਹਾਡੇ ਕੋਡ ਦੀ ਗੁਣਵੱਤਾ ਅਤੇ ਭਰੋਸੇਯੋਗਤਾ ਵਿੱਚ ਸੁਧਾਰ ਕਰਨ ਵਿੱਚ ਚੰਗੀ ਕਿਸਮਤ!
ਜੇਕਰ ਤੁਸੀਂ ਇਸ ਲੇਖ ਨੂੰ ਅੰਗਰੇਜ਼ੀ ਬੋਲਣ ਵਾਲੇ ਦਰਸ਼ਕਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ ਅਨੁਵਾਦ ਲਿੰਕ ਦੀ ਵਰਤੋਂ ਕਰੋ: ਐਂਡਰੀ ਕਾਰਪੋਵ।
ਸਰੋਤ: www.habr.com