PVS-ਸਟੂਡੀਓ ਐਨਾਲਾਈਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM 8 ਵਿੱਚ ਬੱਗ ਲੱਭਣੇ

PVS-ਸਟੂਡੀਓ ਐਨਾਲਾਈਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM 8 ਵਿੱਚ ਬੱਗ ਲੱਭਣੇ
ਸਾਡੇ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM ਪ੍ਰੋਜੈਕਟ ਦੀ ਆਖਰੀ ਕੋਡ ਜਾਂਚ ਤੋਂ ਦੋ ਸਾਲ ਤੋਂ ਵੱਧ ਸਮਾਂ ਬੀਤ ਚੁੱਕਾ ਹੈ। ਆਓ ਇਹ ਯਕੀਨੀ ਕਰੀਏ ਕਿ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਅਜੇ ਵੀ ਤਰੁੱਟੀਆਂ ਅਤੇ ਸੰਭਾਵੀ ਕਮਜ਼ੋਰੀਆਂ ਦੀ ਪਛਾਣ ਕਰਨ ਲਈ ਇੱਕ ਪ੍ਰਮੁੱਖ ਸਾਧਨ ਹੈ। ਅਜਿਹਾ ਕਰਨ ਲਈ, ਅਸੀਂ LLVM 8.0.0 ਰੀਲੀਜ਼ ਵਿੱਚ ਨਵੀਆਂ ਗਲਤੀਆਂ ਦੀ ਜਾਂਚ ਕਰਾਂਗੇ ਅਤੇ ਲੱਭਾਂਗੇ।

ਲੇਖ ਲਿਖਿਆ ਜਾਣਾ ਹੈ

ਇਮਾਨਦਾਰ ਹੋਣ ਲਈ, ਮੈਂ ਇਹ ਲੇਖ ਨਹੀਂ ਲਿਖਣਾ ਚਾਹੁੰਦਾ ਸੀ. ਕਿਸੇ ਪ੍ਰੋਜੈਕਟ ਬਾਰੇ ਲਿਖਣਾ ਦਿਲਚਸਪ ਨਹੀਂ ਹੈ ਜਿਸਦੀ ਅਸੀਂ ਪਹਿਲਾਂ ਹੀ ਕਈ ਵਾਰ ਜਾਂਚ ਕਰ ਚੁੱਕੇ ਹਾਂ (1, 2, 3). ਕੁਝ ਨਵਾਂ ਲਿਖਣਾ ਬਿਹਤਰ ਹੈ, ਪਰ ਮੇਰੇ ਕੋਲ ਕੋਈ ਵਿਕਲਪ ਨਹੀਂ ਹੈ।

ਹਰ ਵਾਰ ਜਦੋਂ LLVM ਦਾ ਨਵਾਂ ਸੰਸਕਰਣ ਜਾਰੀ ਜਾਂ ਅਪਡੇਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਕਲੈਂਗ ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ, ਸਾਨੂੰ ਸਾਡੀ ਮੇਲ ਵਿੱਚ ਹੇਠ ਲਿਖੀ ਕਿਸਮ ਦੇ ਸਵਾਲ ਪ੍ਰਾਪਤ ਹੁੰਦੇ ਹਨ:

ਦੇਖੋ, ਕਲੈਂਗ ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ ਦੇ ਨਵੇਂ ਸੰਸਕਰਣ ਨੇ ਨਵੀਆਂ ਗਲਤੀਆਂ ਲੱਭਣਾ ਸਿੱਖ ਲਿਆ ਹੈ! ਇਹ ਮੈਨੂੰ ਜਾਪਦਾ ਹੈ ਕਿ ਪੀਵੀਐਸ-ਸਟੂਡੀਓ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਸਾਰਥਕਤਾ ਘੱਟ ਰਹੀ ਹੈ. Clang ਪਹਿਲਾਂ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਤਰੁੱਟੀਆਂ ਲੱਭਦਾ ਹੈ ਅਤੇ PVS-ਸਟੂਡੀਓ ਦੀਆਂ ਸਮਰੱਥਾਵਾਂ ਨੂੰ ਫੜਦਾ ਹੈ। ਤੁਸੀਂ ਇਸ ਬਾਰੇ ਕੀ ਸੋਚਦੇ ਹੋ?

ਇਸ ਲਈ ਮੈਂ ਹਮੇਸ਼ਾ ਕੁਝ ਅਜਿਹਾ ਜਵਾਬ ਦੇਣਾ ਚਾਹੁੰਦਾ ਹਾਂ:

ਅਸੀਂ ਵੀ ਵਿਹਲੇ ਨਹੀਂ ਬੈਠਦੇ! ਅਸੀਂ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀਆਂ ਸਮਰੱਥਾਵਾਂ ਵਿੱਚ ਮਹੱਤਵਪੂਰਨ ਸੁਧਾਰ ਕੀਤਾ ਹੈ। ਇਸ ਲਈ ਚਿੰਤਾ ਨਾ ਕਰੋ, ਅਸੀਂ ਪਹਿਲਾਂ ਵਾਂਗ ਅਗਵਾਈ ਕਰਦੇ ਰਹਿੰਦੇ ਹਾਂ।

ਬਦਕਿਸਮਤੀ ਨਾਲ, ਇਹ ਇੱਕ ਬੁਰਾ ਜਵਾਬ ਹੈ. ਇਸ ਵਿੱਚ ਕੋਈ ਸਬੂਤ ਨਹੀਂ ਹਨ। ਅਤੇ ਇਸ ਲਈ ਮੈਂ ਹੁਣ ਇਹ ਲੇਖ ਲਿਖ ਰਿਹਾ ਹਾਂ. ਇਸ ਲਈ, ਐਲਐਲਵੀਐਮ ਪ੍ਰੋਜੈਕਟ ਦੀ ਇੱਕ ਵਾਰ ਫਿਰ ਜਾਂਚ ਕੀਤੀ ਗਈ ਹੈ ਅਤੇ ਇਸ ਵਿੱਚ ਕਈ ਤਰ੍ਹਾਂ ਦੀਆਂ ਤਰੁੱਟੀਆਂ ਪਾਈਆਂ ਗਈਆਂ ਹਨ। ਮੈਂ ਹੁਣ ਉਹਨਾਂ ਦਾ ਪ੍ਰਦਰਸ਼ਨ ਕਰਾਂਗਾ ਜੋ ਮੈਨੂੰ ਦਿਲਚਸਪ ਲੱਗਦੇ ਸਨ। ਕਲੈਂਗ ਸਟੈਟਿਕ ਐਨਾਲਾਈਜ਼ਰ ਇਹ ਤਰੁੱਟੀਆਂ ਨਹੀਂ ਲੱਭ ਸਕਦਾ (ਜਾਂ ਇਸਦੀ ਮਦਦ ਨਾਲ ਅਜਿਹਾ ਕਰਨਾ ਬਹੁਤ ਅਸੁਵਿਧਾਜਨਕ ਹੈ)। ਪਰ ਅਸੀਂ ਕਰ ਸਕਦੇ ਹਾਂ। ਇਸ ਤੋਂ ਇਲਾਵਾ, ਮੈਂ ਇੱਕ ਸ਼ਾਮ ਵਿੱਚ ਇਹ ਸਾਰੀਆਂ ਗਲਤੀਆਂ ਲੱਭੀਆਂ ਅਤੇ ਲਿਖ ਦਿੱਤੀਆਂ।

ਪਰ ਲੇਖ ਲਿਖਣ ਵਿੱਚ ਕਈ ਹਫ਼ਤੇ ਲੱਗ ਗਏ। ਮੈਂ ਇਹ ਸਭ ਟੈਕਸਟ ਵਿੱਚ ਪਾਉਣ ਲਈ ਆਪਣੇ ਆਪ ਨੂੰ ਨਹੀਂ ਲਿਆ ਸਕਿਆ :).

ਤਰੀਕੇ ਨਾਲ, ਜੇ ਤੁਸੀਂ ਇਸ ਵਿੱਚ ਦਿਲਚਸਪੀ ਰੱਖਦੇ ਹੋ ਕਿ ਪੀਵੀਐਸ-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਵਿੱਚ ਗਲਤੀਆਂ ਅਤੇ ਸੰਭਾਵੀ ਕਮਜ਼ੋਰੀਆਂ ਦੀ ਪਛਾਣ ਕਰਨ ਲਈ ਕਿਹੜੀਆਂ ਤਕਨੀਕਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾਂਦੀ ਹੈ, ਤਾਂ ਮੈਂ ਇਸ ਤੋਂ ਜਾਣੂ ਹੋਣ ਦਾ ਸੁਝਾਅ ਦਿੰਦਾ ਹਾਂ ਨੋਟ.

ਨਵੇਂ ਅਤੇ ਪੁਰਾਣੇ ਨਿਦਾਨ

ਜਿਵੇਂ ਕਿ ਪਹਿਲਾਂ ਹੀ ਨੋਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਲਗਭਗ ਦੋ ਸਾਲ ਪਹਿਲਾਂ LLVM ਪ੍ਰੋਜੈਕਟ ਦੀ ਇੱਕ ਵਾਰ ਫਿਰ ਜਾਂਚ ਕੀਤੀ ਗਈ ਸੀ, ਅਤੇ ਪਾਈਆਂ ਗਈਆਂ ਗਲਤੀਆਂ ਨੂੰ ਠੀਕ ਕੀਤਾ ਗਿਆ ਸੀ। ਹੁਣ ਇਹ ਲੇਖ ਗਲਤੀਆਂ ਦਾ ਇੱਕ ਨਵਾਂ ਬੈਚ ਪੇਸ਼ ਕਰੇਗਾ। ਨਵੇਂ ਬੱਗ ਕਿਉਂ ਮਿਲੇ? ਇਸਦੇ 3 ਕਾਰਨ ਹਨ:

  1. LLVM ਪ੍ਰੋਜੈਕਟ ਵਿਕਸਿਤ ਹੋ ਰਿਹਾ ਹੈ, ਪੁਰਾਣਾ ਕੋਡ ਬਦਲ ਰਿਹਾ ਹੈ ਅਤੇ ਨਵਾਂ ਕੋਡ ਜੋੜ ਰਿਹਾ ਹੈ। ਕੁਦਰਤੀ ਤੌਰ 'ਤੇ, ਸੰਸ਼ੋਧਿਤ ਅਤੇ ਲਿਖਤੀ ਕੋਡ ਵਿੱਚ ਨਵੀਆਂ ਗਲਤੀਆਂ ਹਨ. ਇਹ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਦਰਸਾਉਂਦਾ ਹੈ ਕਿ ਸਥਿਰ ਵਿਸ਼ਲੇਸ਼ਣ ਨੂੰ ਨਿਯਮਤ ਤੌਰ 'ਤੇ ਵਰਤਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ, ਅਤੇ ਕਦੇ-ਕਦਾਈਂ ਨਹੀਂ। ਸਾਡੇ ਲੇਖ PVS-ਸਟੂਡੀਓ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀਆਂ ਸਮਰੱਥਾਵਾਂ ਨੂੰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਦਿਖਾਉਂਦੇ ਹਨ, ਪਰ ਇਸਦਾ ਕੋਡ ਗੁਣਵੱਤਾ ਨੂੰ ਸੁਧਾਰਨ ਅਤੇ ਗਲਤੀਆਂ ਨੂੰ ਠੀਕ ਕਰਨ ਦੀ ਲਾਗਤ ਨੂੰ ਘਟਾਉਣ ਨਾਲ ਕੋਈ ਲੈਣਾ-ਦੇਣਾ ਨਹੀਂ ਹੈ। ਨਿਯਮਿਤ ਤੌਰ 'ਤੇ ਸਥਿਰ ਕੋਡ ਵਿਸ਼ਲੇਸ਼ਕ ਦੀ ਵਰਤੋਂ ਕਰੋ!
  2. ਅਸੀਂ ਮੌਜੂਦਾ ਡਾਇਗਨੌਸਟਿਕਸ ਨੂੰ ਅੰਤਿਮ ਰੂਪ ਦੇ ਰਹੇ ਹਾਂ ਅਤੇ ਸੁਧਾਰ ਕਰ ਰਹੇ ਹਾਂ। ਇਸ ਲਈ, ਵਿਸ਼ਲੇਸ਼ਕ ਗਲਤੀਆਂ ਦੀ ਪਛਾਣ ਕਰ ਸਕਦਾ ਹੈ ਜੋ ਇਸਨੇ ਪਿਛਲੇ ਸਕੈਨ ਦੌਰਾਨ ਧਿਆਨ ਨਹੀਂ ਦਿੱਤਾ ਸੀ।
  3. 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V501 [CWE-570] '||' ਦੇ ਖੱਬੇ ਅਤੇ ਸੱਜੇ ਪਾਸੇ 'Name.startswith("avx512.mask.permvar.")' ਇੱਕੋ ਜਿਹੇ ਉਪ-ਸਮੀਕਰਨ ਹਨ। ਆਪਰੇਟਰ AutoUpgrade.cpp 73

ਇਹ ਦੋ ਵਾਰ ਜਾਂਚ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਕਿ ਨਾਮ ਸਬਸਟਰਿੰਗ "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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V502 [CWE-783] ਸ਼ਾਇਦ '?:' ਆਪਰੇਟਰ ਉਮੀਦ ਨਾਲੋਂ ਵੱਖਰੇ ਤਰੀਕੇ ਨਾਲ ਕੰਮ ਕਰਦਾ ਹੈ। '?:' ਆਪਰੇਟਰ ਦੀ '==' ਆਪਰੇਟਰ ਨਾਲੋਂ ਘੱਟ ਤਰਜੀਹ ਹੈ। PPCTargetTransformInfo.cpp 404

ਮੇਰੇ ਵਿਚਾਰ ਵਿੱਚ, ਇਹ ਇੱਕ ਬਹੁਤ ਹੀ ਸੁੰਦਰ ਗਲਤੀ ਹੈ. ਹਾਂ, ਮੈਨੂੰ ਪਤਾ ਹੈ ਕਿ ਮੇਰੇ ਕੋਲ ਸੁੰਦਰਤਾ ਬਾਰੇ ਅਜੀਬ ਵਿਚਾਰ ਹਨ :).

ਹੁਣ, ਅਨੁਸਾਰ ਆਪਰੇਟਰ ਦੀਆਂ ਤਰਜੀਹਾਂ, ਸਮੀਕਰਨ ਦਾ ਮੁਲਾਂਕਣ ਇਸ ਤਰ੍ਹਾਂ ਕੀਤਾ ਗਿਆ ਹੈ:

(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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V522 [CWE-476] ਨਲ ਪੁਆਇੰਟਰ 'LHS' ਦਾ ਹਵਾਲਾ ਦਿੱਤਾ ਜਾ ਸਕਦਾ ਹੈ। TGParser.cpp 2152

ਜੇ ਪੁਆਇੰਟਰ ਐਲਐਚਐਸ ਖਾਲੀ ਹੈ, ਇੱਕ ਚੇਤਾਵਨੀ ਜਾਰੀ ਕੀਤੀ ਜਾਣੀ ਚਾਹੀਦੀ ਹੈ. ਹਾਲਾਂਕਿ, ਇਸਦੀ ਬਜਾਏ, ਇਹ ਉਹੀ ਨਲ ਪੁਆਇੰਟਰ ਡੀਰੇਫਰੈਂਡ ਕੀਤਾ ਜਾਵੇਗਾ: 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V570 'Identifier->Type' ਵੇਰੀਏਬਲ ਆਪਣੇ ਆਪ ਨੂੰ ਨਿਰਧਾਰਤ ਕੀਤਾ ਗਿਆ ਹੈ। FormatTokenLexer.cpp 249

ਆਪਣੇ ਆਪ ਨੂੰ ਇੱਕ ਵੇਰੀਏਬਲ ਨਿਰਧਾਰਤ ਕਰਨ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ. ਜ਼ਿਆਦਾਤਰ ਉਹ ਲਿਖਣਾ ਚਾਹੁੰਦੇ ਸਨ:

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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V622 [CWE-478] 'ਸਵਿੱਚ' ਸਟੇਟਮੈਂਟ ਦੀ ਜਾਂਚ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। ਇਹ ਸੰਭਵ ਹੈ ਕਿ ਪਹਿਲਾ 'ਕੇਸ' ਆਪਰੇਟਰ ਗੁੰਮ ਹੈ। SystemZAsmParser.cpp 652

ਸ਼ੁਰੂ ਵਿੱਚ ਇੱਕ ਬਹੁਤ ਹੀ ਸ਼ੱਕੀ ਓਪਰੇਟਰ ਹੈ ਬ੍ਰੇਕ. ਕੀ ਤੁਸੀਂ ਇੱਥੇ ਕੁਝ ਹੋਰ ਲਿਖਣਾ ਭੁੱਲ ਗਏ ਹੋ?

ਫਰੈਗਮੈਂਟ 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V595 [CWE-476] 'ਕੈਲੀ' ਪੁਆਇੰਟਰ ਨੂੰ nullptr ਦੇ ਵਿਰੁੱਧ ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਵਰਤਿਆ ਗਿਆ ਸੀ। ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 172, 174. AMDGPUInline.cpp 172

ਪੁਆਇੰਟਰ ਕੈਲੀ ਫੰਕਸ਼ਨ ਨੂੰ ਬੁਲਾਏ ਜਾਣ ਸਮੇਂ ਸ਼ੁਰੂ ਵਿੱਚ ਡੀਰੇਫਰੈਂਸ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਪ੍ਰਾਪਤ ਕਰੋ.

ਅਤੇ ਫਿਰ ਇਹ ਪਤਾ ਚਲਦਾ ਹੈ ਕਿ ਇਸ ਪੁਆਇੰਟਰ ਨੂੰ ਸਮਾਨਤਾ ਲਈ ਜਾਂਚਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V629 [CWE-190] '~(ਆਕਾਰ - 1) << 1' ਸਮੀਕਰਨ ਦਾ ਨਿਰੀਖਣ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। 32-ਬਿੱਟ ਕਿਸਮ ਦੇ ਬਾਅਦ ਦੇ ਵਿਸਥਾਰ ਦੇ ਨਾਲ 64-ਬਿੱਟ ਮੁੱਲ ਦਾ ਬਿੱਟ ਸ਼ਿਫਟ ਕਰਨਾ। AArch64AddressingModes.h 260

ਇਹ ਇੱਕ ਬੱਗ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ ਅਤੇ ਕੋਡ ਬਿਲਕੁਲ ਇਰਾਦੇ ਅਨੁਸਾਰ ਕੰਮ ਕਰਦਾ ਹੈ। ਪਰ ਇਹ ਸਪੱਸ਼ਟ ਤੌਰ 'ਤੇ ਇੱਕ ਬਹੁਤ ਹੀ ਸ਼ੱਕੀ ਜਗ੍ਹਾ ਹੈ ਅਤੇ ਇਸਦੀ ਜਾਂਚ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।

ਚਲੋ ਵੇਰੀਏਬਲ ਕਹੀਏ ਆਕਾਰ 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V646 [CWE-670] ਐਪਲੀਕੇਸ਼ਨ ਦੇ ਤਰਕ ਦੀ ਜਾਂਚ ਕਰਨ 'ਤੇ ਵਿਚਾਰ ਕਰੋ। ਇਹ ਸੰਭਵ ਹੈ ਕਿ 'ਹੋਰ' ਕੀਵਰਡ ਗੁੰਮ ਹੈ। AMDGPUAsmParser.cpp 5655

ਇੱਥੇ ਕੋਈ ਗਲਤੀ ਨਹੀਂ ਹੈ। ਪਹਿਲੇ ਦੇ ਫਿਰ-ਬਲਾਕ ਤੋਂ ਲੈ ਕੇ 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-ਸਟੂਡੀਓ ਐਨਾਲਾਈਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM 8 ਵਿੱਚ ਬੱਗ ਲੱਭਣੇ

PVS-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V708 [CWE-758] ਖਤਰਨਾਕ ਉਸਾਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾਂਦੀ ਹੈ: 'FeaturesMap[Op] = FeaturesMap.size()', ਜਿੱਥੇ 'featuresMap' 'map' ਕਲਾਸ ਦਾ ਹੈ। ਇਹ ਅਣ-ਪ੍ਰਭਾਸ਼ਿਤ ਵਿਵਹਾਰ ਦੀ ਅਗਵਾਈ ਕਰ ਸਕਦਾ ਹੈ. RISCVCompressInstEmitter.cpp 490

ਸਮੱਸਿਆ ਲਾਈਨ:

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] 'NType' ਵੇਰੀਏਬਲ ਨੂੰ ਲਗਾਤਾਰ ਦੋ ਵਾਰ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਸ਼ਾਇਦ ਇਹ ਇੱਕ ਗਲਤੀ ਹੈ. ਲਾਈਨਾਂ ਦੀ ਜਾਂਚ ਕਰੋ: 1663, 1664. MachOObjectFile.cpp 1664

ਮੈਨੂੰ ਨਹੀਂ ਲੱਗਦਾ ਕਿ ਇੱਥੇ ਕੋਈ ਅਸਲ ਗਲਤੀ ਹੈ। ਸਿਰਫ਼ ਇੱਕ ਬੇਲੋੜੀ ਦੁਹਰਾਈ ਗਈ ਅਸਾਈਨਮੈਂਟ। ਪਰ ਫਿਰ ਵੀ ਇੱਕ ਗਲਤੀ.

ਇਸੇ ਤਰ੍ਹਾਂ:

  • 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V547 [CWE-571] ਸਮੀਕਰਨ 'nextByte != 0x90' ਹਮੇਸ਼ਾ ਸੱਚ ਹੁੰਦਾ ਹੈ। X86DisassemblerDecoder.cpp 379

ਜਾਂਚ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ। ਵੇਰੀਏਬਲ nextByte ਹਮੇਸ਼ਾ ਮੁੱਲ ਦੇ ਬਰਾਬਰ ਨਹੀਂ ਹੁੰਦਾ 0x90, ਜੋ ਕਿ ਪਿਛਲੀ ਜਾਂਚ ਤੋਂ ਬਾਅਦ ਹੈ। ਇਹ ਕਿਸੇ ਤਰ੍ਹਾਂ ਦੀ ਲਾਜ਼ੀਕਲ ਗਲਤੀ ਹੈ।

Fragment N29 - N...: ਹਮੇਸ਼ਾ ਸਹੀ/ਗਲਤ ਸਥਿਤੀਆਂ

ਵਿਸ਼ਲੇਸ਼ਕ ਬਹੁਤ ਸਾਰੀਆਂ ਚੇਤਾਵਨੀਆਂ ਜਾਰੀ ਕਰਦਾ ਹੈ ਕਿ ਸਾਰੀ ਸਥਿਤੀ (V547) ਜਾਂ ਇਸਦਾ ਹਿੱਸਾ (V560) ਹਮੇਸ਼ਾ ਸਹੀ ਜਾਂ ਗਲਤ ਹੁੰਦਾ ਹੈ। ਅਕਸਰ ਇਹ ਅਸਲ ਗਲਤੀਆਂ ਨਹੀਂ ਹੁੰਦੀਆਂ, ਪਰ ਸਿਰਫ਼ ਢਲਾਣ ਵਾਲਾ ਕੋਡ, ਮੈਕਰੋ ਵਿਸਥਾਰ ਦਾ ਨਤੀਜਾ, ਅਤੇ ਇਸ ਤਰ੍ਹਾਂ ਦੀਆਂ। ਹਾਲਾਂਕਿ, ਇਹਨਾਂ ਸਾਰੀਆਂ ਚੇਤਾਵਨੀਆਂ ਨੂੰ ਦੇਖਣਾ ਸਮਝਦਾਰ ਹੈ, ਕਿਉਂਕਿ ਸਮੇਂ-ਸਮੇਂ 'ਤੇ ਅਸਲ ਤਰਕ ਸੰਬੰਧੀ ਗਲਤੀਆਂ ਹੁੰਦੀਆਂ ਹਨ। ਉਦਾਹਰਨ ਲਈ, ਕੋਡ ਦਾ ਇਹ ਭਾਗ ਸ਼ੱਕੀ ਹੈ:

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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V560 [CWE-570] ਕੰਡੀਸ਼ਨਲ ਸਮੀਕਰਨ ਦਾ ਇੱਕ ਹਿੱਸਾ ਹਮੇਸ਼ਾ ਗਲਤ ਹੁੰਦਾ ਹੈ: RegNo == 0xe। ARMDisassembler.cpp 939

ਸਥਿਰ 0xE ਦਸ਼ਮਲਵ ਵਿੱਚ ਮੁੱਲ 14 ਹੈ। ਇਮਤਿਹਾਨ RegNo == 0xe ਇਸ ਦਾ ਕੋਈ ਮਤਲਬ ਨਹੀਂ ਹੈ ਕਿਉਂਕਿ ਜੇ RegNo > 13, ਫਿਰ ਫੰਕਸ਼ਨ ਆਪਣਾ ਐਗਜ਼ੀਕਿਊਸ਼ਨ ਪੂਰਾ ਕਰੇਗਾ।

IDs V547 ਅਤੇ V560 ਦੇ ਨਾਲ ਕਈ ਹੋਰ ਚੇਤਾਵਨੀਆਂ ਸਨ, ਪਰ ਜਿਵੇਂ ਕਿ V595, ਮੈਨੂੰ ਇਹਨਾਂ ਚੇਤਾਵਨੀਆਂ ਦਾ ਅਧਿਐਨ ਕਰਨ ਵਿੱਚ ਕੋਈ ਦਿਲਚਸਪੀ ਨਹੀਂ ਸੀ। ਇਹ ਪਹਿਲਾਂ ਹੀ ਸਪੱਸ਼ਟ ਸੀ ਕਿ ਮੇਰੇ ਕੋਲ ਲੇਖ ਲਿਖਣ ਲਈ ਕਾਫੀ ਸਮੱਗਰੀ ਸੀ :). ਇਸ ਲਈ, ਇਹ ਅਣਜਾਣ ਹੈ ਕਿ PVS-ਸਟੂਡੀਓ ਦੀ ਵਰਤੋਂ ਕਰਕੇ LLVM ਵਿੱਚ ਇਸ ਕਿਸਮ ਦੀਆਂ ਕਿੰਨੀਆਂ ਗਲਤੀਆਂ ਦੀ ਪਛਾਣ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।

ਮੈਂ ਤੁਹਾਨੂੰ ਇੱਕ ਉਦਾਹਰਣ ਦੇਵਾਂਗਾ ਕਿ ਇਹਨਾਂ ਟਰਿਗਰਾਂ ਦਾ ਅਧਿਐਨ ਕਰਨਾ ਬੋਰਿੰਗ ਕਿਉਂ ਹੈ. ਵਿਸ਼ਲੇਸ਼ਕ ਹੇਠਾਂ ਦਿੱਤੇ ਕੋਡ ਲਈ ਚੇਤਾਵਨੀ ਜਾਰੀ ਕਰਨ ਵਿੱਚ ਬਿਲਕੁਲ ਸਹੀ ਹੈ। ਪਰ ਇਹ ਕੋਈ ਗਲਤੀ ਨਹੀਂ ਹੈ।

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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V612 [CWE-670] ਇੱਕ ਲੂਪ ਦੇ ਅੰਦਰ ਇੱਕ ਬਿਨਾਂ ਸ਼ਰਤ 'ਵਾਪਸੀ'। R600OptimizeVectorRegisters.cpp 63

ਇਹ ਜਾਂ ਤਾਂ ਇੱਕ ਗਲਤੀ ਹੈ ਜਾਂ ਇੱਕ ਖਾਸ ਤਕਨੀਕ ਹੈ ਜਿਸਦਾ ਉਦੇਸ਼ ਕੋਡ ਨੂੰ ਪੜ੍ਹਨ ਵਾਲੇ ਪ੍ਰੋਗਰਾਮਰਾਂ ਨੂੰ ਕੁਝ ਸਮਝਾਉਣਾ ਹੈ। ਇਹ ਡਿਜ਼ਾਈਨ ਮੈਨੂੰ ਕੁਝ ਨਹੀਂ ਸਮਝਾਉਂਦਾ ਅਤੇ ਬਹੁਤ ਸ਼ੱਕੀ ਲੱਗਦਾ ਹੈ। ਇਸ ਤਰ੍ਹਾਂ ਨਾ ਲਿਖਣਾ ਬਿਹਤਰ ਹੈ :)।

ਥੱਕ ਗਏ? ਫਿਰ ਚਾਹ ਜਾਂ ਕੌਫੀ ਬਣਾਉਣ ਦਾ ਸਮਾਂ ਆ ਗਿਆ।

PVS-ਸਟੂਡੀਓ ਐਨਾਲਾਈਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM 8 ਵਿੱਚ ਬੱਗ ਲੱਭਣੇ

ਨਵੇਂ ਡਾਇਗਨੌਸਟਿਕਸ ਦੁਆਰਾ ਪਛਾਣੇ ਗਏ ਨੁਕਸ

ਮੈਨੂੰ ਲਗਦਾ ਹੈ ਕਿ ਪੁਰਾਣੇ ਡਾਇਗਨੌਸਟਿਕਸ ਦੀਆਂ 30 ਸਰਗਰਮੀਆਂ ਕਾਫ਼ੀ ਹਨ. ਆਓ ਹੁਣ ਦੇਖਦੇ ਹਾਂ ਕਿ ਨਵੇਂ ਡਾਇਗਨੌਸਟਿਕਸ ਨਾਲ ਕਿਹੜੀਆਂ ਦਿਲਚਸਪ ਚੀਜ਼ਾਂ ਲੱਭੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ ਜੋ ਬਾਅਦ ਵਿੱਚ ਵਿਸ਼ਲੇਸ਼ਕ ਵਿੱਚ ਪ੍ਰਗਟ ਹੋਈਆਂ ਪਿਛਲਾ ਜਾਂਚਾਂ ਇਸ ਸਮੇਂ ਦੌਰਾਨ, C++ ਵਿਸ਼ਲੇਸ਼ਕ ਵਿੱਚ ਕੁੱਲ 66 ਆਮ-ਉਦੇਸ਼ ਦੇ ਡਾਇਗਨੌਸਟਿਕਸ ਸ਼ਾਮਲ ਕੀਤੇ ਗਏ ਸਨ।

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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V779 [CWE-561] ਪਹੁੰਚਯੋਗ ਕੋਡ ਖੋਜਿਆ ਗਿਆ। ਇਹ ਸੰਭਵ ਹੈ ਕਿ ਕੋਈ ਗਲਤੀ ਮੌਜੂਦ ਹੈ। ExecutionUtils.cpp 146

ਜਿਵੇਂ ਕਿ ਤੁਸੀਂ ਦੇਖ ਸਕਦੇ ਹੋ, ਆਪਰੇਟਰ ਦੀਆਂ ਦੋਵੇਂ ਸ਼ਾਖਾਵਾਂ 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V784 ਬਿੱਟ ਮਾਸਕ ਦਾ ਆਕਾਰ ਪਹਿਲੇ ਓਪਰੇਂਡ ਦੇ ਆਕਾਰ ਤੋਂ ਘੱਟ ਹੈ। ਇਹ ਉੱਚ ਬਿੱਟਾਂ ਦੇ ਨੁਕਸਾਨ ਦਾ ਕਾਰਨ ਬਣੇਗਾ. RuntimeDyld.cpp 815

ਕਿਰਪਾ ਕਰਕੇ ਧਿਆਨ ਦਿਓ ਕਿ ਫੰਕਸ਼ਨ 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V1028 [CWE-190] ਸੰਭਵ ਓਵਰਫਲੋ। 'NumElts * ਸਕੇਲ' ਆਪਰੇਟਰ ਦੇ 'ਸਾਈਜ਼_ਟੀ' ਕਿਸਮ ਲਈ ਕਾਸਟਿੰਗ ਓਪਰੇਂਡ 'ਤੇ ਵਿਚਾਰ ਕਰੋ, ਨਤੀਜਾ ਨਹੀਂ। X86ISelLowering.h 1577

ਟਾਈਪ ਵੇਰੀਏਬਲ ਨੂੰ ਗੁਣਾ ਕਰਨ ਵੇਲੇ ਓਵਰਫਲੋ ਤੋਂ ਬਚਣ ਲਈ ਸਪੱਸ਼ਟ ਕਿਸਮ ਦੀ ਕਾਸਟਿੰਗ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਇੰਟ. ਹਾਲਾਂਕਿ, ਇੱਥੇ ਸਪਸ਼ਟ ਕਿਸਮ ਦੀ ਕਾਸਟਿੰਗ ਓਵਰਫਲੋ ਤੋਂ ਸੁਰੱਖਿਆ ਨਹੀਂ ਕਰਦੀ ਹੈ। ਪਹਿਲਾਂ, ਵੇਰੀਏਬਲ ਨੂੰ ਗੁਣਾ ਕੀਤਾ ਜਾਵੇਗਾ, ਅਤੇ ਕੇਵਲ ਤਦ ਹੀ ਗੁਣਾ ਦੇ 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;
  }
  ....
}

V778 [CWE-682] ਦੋ ਸਮਾਨ ਕੋਡ ਦੇ ਟੁਕੜੇ ਮਿਲੇ ਹਨ। ਸ਼ਾਇਦ, ਇਹ ਇੱਕ ਟਾਈਪੋ ਹੈ ਅਤੇ 'Op1' ਦੀ ਬਜਾਏ 'Op0' ਵੇਰੀਏਬਲ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾਣੀ ਚਾਹੀਦੀ ਹੈ। InstCombineCompares.cpp 5507

ਇਹ ਨਵਾਂ ਦਿਲਚਸਪ ਡਾਇਗਨੌਸਟਿਕ ਉਹਨਾਂ ਸਥਿਤੀਆਂ ਦੀ ਪਛਾਣ ਕਰਦਾ ਹੈ ਜਿੱਥੇ ਕੋਡ ਦੇ ਇੱਕ ਟੁਕੜੇ ਦੀ ਨਕਲ ਕੀਤੀ ਗਈ ਹੈ ਅਤੇ ਇਸ ਵਿੱਚ ਕੁਝ ਨਾਮ ਬਦਲੇ ਜਾਣੇ ਸ਼ੁਰੂ ਹੋ ਗਏ ਹਨ, ਪਰ ਇੱਕ ਥਾਂ ਤੇ ਉਹਨਾਂ ਨੇ ਇਸਨੂੰ ਠੀਕ ਨਹੀਂ ਕੀਤਾ ਹੈ।

ਕਿਰਪਾ ਕਰਕੇ ਧਿਆਨ ਦਿਓ ਕਿ ਦੂਜੇ ਬਲਾਕ ਵਿੱਚ ਉਹ ਬਦਲ ਗਏ ਹਨ 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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V1001 [CWE-563] 'ਮੋਡ' ਵੇਰੀਏਬਲ ਨਿਰਧਾਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਪਰ ਫੰਕਸ਼ਨ ਦੇ ਅੰਤ ਤੱਕ ਵਰਤਿਆ ਨਹੀਂ ਜਾਂਦਾ ਹੈ। SIModeRegister.cpp 48

ਫੰਕਸ਼ਨ ਆਰਗੂਮੈਂਟਾਂ ਨੂੰ ਕਲਾਸ ਮੈਂਬਰਾਂ ਦੇ ਸਮਾਨ ਨਾਮ ਦੇਣਾ ਬਹੁਤ ਖਤਰਨਾਕ ਹੈ। ਇਹ ਉਲਝਣ ਵਿੱਚ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ ਬਹੁਤ ਹੀ ਆਸਾਨ ਹੈ. ਸਾਡੇ ਸਾਹਮਣੇ ਅਜਿਹਾ ਹੀ ਮਾਮਲਾ ਹੈ। ਇਹ ਸਮੀਕਰਨ ਅਰਥ ਨਹੀਂ ਰੱਖਦਾ:

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: ਉਹ ਸੂਚਕਾਂਕ ਦੀ ਜਾਂਚ ਕਰਨਾ ਭੁੱਲ ਗਏ

ਪਹਿਲਾਂ, ਅਸੀਂ ਡਾਇਗਨੌਸਟਿਕ ਟਰਿਗਰਿੰਗ ਦੀਆਂ ਉਦਾਹਰਣਾਂ ਨੂੰ ਦੇਖਿਆ ਸੀ V595. ਇਸ ਦਾ ਸਾਰ ਇਹ ਹੈ ਕਿ ਪੁਆਇੰਟਰ ਨੂੰ ਸ਼ੁਰੂ ਵਿੱਚ ਡੀਰੇਫਰੈਂਸ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਅਤੇ ਕੇਵਲ ਤਦ ਹੀ ਜਾਂਚਿਆ ਜਾਂਦਾ ਹੈ. ਨੌਜਵਾਨ ਨਿਦਾਨ V1004 ਅਰਥ ਵਿੱਚ ਉਲਟ ਹੈ, ਪਰ ਇਹ ਬਹੁਤ ਸਾਰੀਆਂ ਗਲਤੀਆਂ ਨੂੰ ਵੀ ਪ੍ਰਗਟ ਕਰਦਾ ਹੈ। ਇਹ ਉਹਨਾਂ ਸਥਿਤੀਆਂ ਦੀ ਪਛਾਣ ਕਰਦਾ ਹੈ ਜਿੱਥੇ ਪੁਆਇੰਟਰ ਦੀ ਸ਼ੁਰੂਆਤ ਵਿੱਚ ਜਾਂਚ ਕੀਤੀ ਗਈ ਸੀ ਅਤੇ ਫਿਰ ਅਜਿਹਾ ਕਰਨਾ ਭੁੱਲ ਗਿਆ ਸੀ। ਆਓ LLVM ਦੇ ਅੰਦਰ ਪਾਏ ਗਏ ਅਜਿਹੇ ਕੇਸਾਂ ਨੂੰ ਵੇਖੀਏ.

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-ਸਟੂਡੀਓ ਚੇਤਾਵਨੀ: V1023 [CWE-460] ਮਾਲਕ ਤੋਂ ਬਿਨਾਂ ਇੱਕ ਪੁਆਇੰਟਰ ਨੂੰ 'emplace_back' ਵਿਧੀ ਦੁਆਰਾ 'ਰਣਨੀਤੀਆਂ' ਕੰਟੇਨਰ ਵਿੱਚ ਜੋੜਿਆ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਅਪਵਾਦ ਦੇ ਮਾਮਲੇ ਵਿੱਚ ਇੱਕ ਮੈਮੋਰੀ ਲੀਕ ਹੋ ਜਾਵੇਗਾ. llvm-isel-fuzzer.cpp 58

ਵਰਗੇ ਇੱਕ ਕੰਟੇਨਰ ਦੇ ਅੰਤ ਵਿੱਚ ਇੱਕ ਤੱਤ ਸ਼ਾਮਿਲ ਕਰਨ ਲਈ 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-ਸਟੂਡੀਓ ਦੀ ਕਾਰਜਪ੍ਰਣਾਲੀ ਨੂੰ ਪ੍ਰਸਿੱਧ ਬਣਾਉਣ ਲਈ ਸਾਡੇ ਦੁਆਰਾ ਕੀਤੇ ਗਏ ਇੱਕ ਆਮ ਦ੍ਰਿਸ਼ ਨਹੀਂ ਹਨ।

ਤੁਹਾਡੇ ਕੋਡ ਦੀ ਗੁਣਵੱਤਾ ਅਤੇ ਭਰੋਸੇਯੋਗਤਾ ਵਿੱਚ ਸੁਧਾਰ ਕਰਨ ਵਿੱਚ ਚੰਗੀ ਕਿਸਮਤ!

PVS-ਸਟੂਡੀਓ ਐਨਾਲਾਈਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ LLVM 8 ਵਿੱਚ ਬੱਗ ਲੱਭਣੇ

ਜੇਕਰ ਤੁਸੀਂ ਇਸ ਲੇਖ ਨੂੰ ਅੰਗਰੇਜ਼ੀ ਬੋਲਣ ਵਾਲੇ ਦਰਸ਼ਕਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ ਅਨੁਵਾਦ ਲਿੰਕ ਦੀ ਵਰਤੋਂ ਕਰੋ: ਐਂਡਰੀ ਕਾਰਪੋਵ। PVS-ਸਟੂਡੀਓ ਨਾਲ LLVM 8 ਵਿੱਚ ਬੱਗ ਲੱਭਣੇ.

ਸਰੋਤ: www.habr.com

ਇੱਕ ਟਿੱਪਣੀ ਜੋੜੋ