PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವನ್ನು ಬಳಸಿಕೊಂಡು LLVM 8 ರಲ್ಲಿ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯುವುದು

PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವನ್ನು ಬಳಸಿಕೊಂಡು LLVM 8 ರಲ್ಲಿ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯುವುದು
ನಮ್ಮ PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವನ್ನು ಬಳಸಿಕೊಂಡು LLVM ಯೋಜನೆಯ ಕೊನೆಯ ಕೋಡ್ ಪರಿಶೀಲನೆಯಿಂದ ಎರಡು ವರ್ಷಗಳು ಕಳೆದಿವೆ. ದೋಷಗಳು ಮತ್ತು ಸಂಭಾವ್ಯ ದುರ್ಬಲತೆಗಳನ್ನು ಗುರುತಿಸಲು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವು ಇನ್ನೂ ಪ್ರಮುಖ ಸಾಧನವಾಗಿದೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳೋಣ. ಇದನ್ನು ಮಾಡಲು, ನಾವು LLVM 8.0.0 ಬಿಡುಗಡೆಯಲ್ಲಿ ಹೊಸ ದೋಷಗಳನ್ನು ಪರಿಶೀಲಿಸುತ್ತೇವೆ ಮತ್ತು ಕಂಡುಹಿಡಿಯುತ್ತೇವೆ.

ಬರೆಯಬೇಕಾದ ಲೇಖನ

ನಿಜ ಹೇಳಬೇಕೆಂದರೆ, ನಾನು ಈ ಲೇಖನವನ್ನು ಬರೆಯಲು ಬಯಸಲಿಲ್ಲ. ನಾವು ಈಗಾಗಲೇ ಹಲವಾರು ಬಾರಿ ಪರಿಶೀಲಿಸಿದ ಯೋಜನೆಯ ಬಗ್ಗೆ ಬರೆಯುವುದು ಆಸಕ್ತಿದಾಯಕವಲ್ಲ (1, 2, 3) ಹೊಸದನ್ನು ಬರೆಯುವುದು ಉತ್ತಮ, ಆದರೆ ನನಗೆ ಯಾವುದೇ ಆಯ್ಕೆ ಇಲ್ಲ.

ಪ್ರತಿ ಬಾರಿ LLVM ನ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲಾಗುತ್ತದೆ ಅಥವಾ ನವೀಕರಿಸಲಾಗುತ್ತದೆ ಕ್ಲಾಂಗ್ ಸ್ಟ್ಯಾಟಿಕ್ ವಿಶ್ಲೇಷಕ, ನಮ್ಮ ಮೇಲ್‌ನಲ್ಲಿ ನಾವು ಈ ಕೆಳಗಿನ ಪ್ರಕಾರದ ಪ್ರಶ್ನೆಗಳನ್ನು ಸ್ವೀಕರಿಸುತ್ತೇವೆ:

ನೋಡಿ, ಕ್ಲಾಂಗ್ ಸ್ಟ್ಯಾಟಿಕ್ ವಿಶ್ಲೇಷಕದ ಹೊಸ ಆವೃತ್ತಿಯು ಹೊಸ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಕಲಿತಿದೆ! PVS-Studio ಅನ್ನು ಬಳಸುವ ಪ್ರಸ್ತುತತೆ ಕಡಿಮೆಯಾಗುತ್ತಿದೆ ಎಂದು ನನಗೆ ತೋರುತ್ತದೆ. ಕ್ಲಾಂಗ್ ಮೊದಲಿಗಿಂತ ಹೆಚ್ಚು ದೋಷಗಳನ್ನು ಕಂಡುಕೊಳ್ಳುತ್ತದೆ ಮತ್ತು PVS-ಸ್ಟುಡಿಯೊದ ಸಾಮರ್ಥ್ಯಗಳೊಂದಿಗೆ ಹಿಡಿಯುತ್ತದೆ. ನೀವು ಇದರ ಬಗ್ಗೆ ಏನನ್ನು ಯೋಚಿಸುತ್ತಿರಿ?

ಇದಕ್ಕೆ ನಾನು ಯಾವಾಗಲೂ ಉತ್ತರಿಸಲು ಬಯಸುತ್ತೇನೆ:

ನಾವೂ ಸುಮ್ಮನೆ ಕೂರುವುದಿಲ್ಲ! PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕದ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ನಾವು ಗಮನಾರ್ಹವಾಗಿ ಸುಧಾರಿಸಿದ್ದೇವೆ. ಆದ್ದರಿಂದ ಚಿಂತಿಸಬೇಡಿ, ನಾವು ಮೊದಲಿನಂತೆಯೇ ಮುನ್ನಡೆಯುತ್ತೇವೆ.

ದುರದೃಷ್ಟವಶಾತ್, ಇದು ಕೆಟ್ಟ ಉತ್ತರವಾಗಿದೆ. ಅದರಲ್ಲಿ ಯಾವುದೇ ಪುರಾವೆಗಳಿಲ್ಲ. ಮತ್ತು ಅದಕ್ಕಾಗಿಯೇ ನಾನು ಈಗ ಈ ಲೇಖನವನ್ನು ಬರೆಯುತ್ತಿದ್ದೇನೆ. ಆದ್ದರಿಂದ, LLVM ಯೋಜನೆಯನ್ನು ಮತ್ತೊಮ್ಮೆ ಪರಿಶೀಲಿಸಲಾಗಿದೆ ಮತ್ತು ಅದರಲ್ಲಿ ವಿವಿಧ ದೋಷಗಳು ಕಂಡುಬಂದಿವೆ. ನನಗೆ ಆಸಕ್ತಿದಾಯಕವೆಂದು ತೋರುವದನ್ನು ನಾನು ಈಗ ಪ್ರದರ್ಶಿಸುತ್ತೇನೆ. ಕ್ಲಾಂಗ್ ಸ್ಟ್ಯಾಟಿಕ್ ವಿಶ್ಲೇಷಕವು ಈ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಸಾಧ್ಯವಿಲ್ಲ (ಅಥವಾ ಅದರ ಸಹಾಯದಿಂದ ಹಾಗೆ ಮಾಡುವುದು ಅತ್ಯಂತ ಅನಾನುಕೂಲವಾಗಿದೆ). ಆದರೆ ನಾವು ಮಾಡಬಹುದು. ಇದಲ್ಲದೆ, ನಾನು ಈ ಎಲ್ಲಾ ದೋಷಗಳನ್ನು ಒಂದೇ ಸಂಜೆಯಲ್ಲಿ ಕಂಡುಕೊಂಡೆ ಮತ್ತು ಬರೆದಿದ್ದೇನೆ.

ಆದರೆ ಲೇಖನವನ್ನು ಬರೆಯಲು ಹಲವಾರು ವಾರಗಳನ್ನು ತೆಗೆದುಕೊಂಡಿತು. ಇದನ್ನೆಲ್ಲ ಪಠ್ಯಕ್ಕೆ ಹಾಕಲು ನನಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ :).

ಮೂಲಕ, ದೋಷಗಳು ಮತ್ತು ಸಂಭಾವ್ಯ ದುರ್ಬಲತೆಗಳನ್ನು ಗುರುತಿಸಲು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕದಲ್ಲಿ ಯಾವ ತಂತ್ರಜ್ಞಾನಗಳನ್ನು ಬಳಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಬಗ್ಗೆ ನೀವು ಆಸಕ್ತಿ ಹೊಂದಿದ್ದರೆ, ನಂತರ ನಾನು ಇದರೊಂದಿಗೆ ಪರಿಚಯ ಮಾಡಿಕೊಳ್ಳಲು ಸಲಹೆ ನೀಡುತ್ತೇನೆ. ಸೂಚನೆ.

ಹೊಸ ಮತ್ತು ಹಳೆಯ ರೋಗನಿರ್ಣಯ

ಈಗಾಗಲೇ ಗಮನಿಸಿದಂತೆ, ಸುಮಾರು ಎರಡು ವರ್ಷಗಳ ಹಿಂದೆ LLVM ಯೋಜನೆಯನ್ನು ಮತ್ತೊಮ್ಮೆ ಪರಿಶೀಲಿಸಲಾಯಿತು, ಮತ್ತು ಕಂಡುಬಂದ ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸಲಾಗಿದೆ. ಈಗ ಈ ಲೇಖನವು ದೋಷಗಳ ಹೊಸ ಬ್ಯಾಚ್ ಅನ್ನು ಪ್ರಸ್ತುತಪಡಿಸುತ್ತದೆ. ಹೊಸ ದೋಷಗಳು ಏಕೆ ಕಂಡುಬಂದಿವೆ? ಇದಕ್ಕೆ 3 ಕಾರಣಗಳಿವೆ:

  1. LLVM ಯೋಜನೆಯು ವಿಕಸನಗೊಳ್ಳುತ್ತಿದೆ, ಹಳೆಯ ಕೋಡ್ ಅನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ ಮತ್ತು ಹೊಸ ಕೋಡ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ. ಸ್ವಾಭಾವಿಕವಾಗಿ, ಮಾರ್ಪಡಿಸಿದ ಮತ್ತು ಲಿಖಿತ ಕೋಡ್‌ನಲ್ಲಿ ಹೊಸ ದೋಷಗಳಿವೆ. ಸ್ಥಿರ ವಿಶ್ಲೇಷಣೆಯನ್ನು ನಿಯಮಿತವಾಗಿ ಬಳಸಬೇಕು ಮತ್ತು ಸಾಂದರ್ಭಿಕವಾಗಿ ಬಳಸಬಾರದು ಎಂದು ಇದು ಸ್ಪಷ್ಟವಾಗಿ ತೋರಿಸುತ್ತದೆ. ನಮ್ಮ ಲೇಖನಗಳು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕದ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಚೆನ್ನಾಗಿ ತೋರಿಸುತ್ತವೆ, ಆದರೆ ಇದು ಕೋಡ್ ಗುಣಮಟ್ಟವನ್ನು ಸುಧಾರಿಸಲು ಮತ್ತು ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸುವ ವೆಚ್ಚವನ್ನು ಕಡಿಮೆ ಮಾಡಲು ಏನೂ ಹೊಂದಿಲ್ಲ. ಸ್ಥಿರ ಕೋಡ್ ವಿಶ್ಲೇಷಕವನ್ನು ನಿಯಮಿತವಾಗಿ ಬಳಸಿ!
  2. ನಾವು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ರೋಗನಿರ್ಣಯವನ್ನು ಅಂತಿಮಗೊಳಿಸುತ್ತಿದ್ದೇವೆ ಮತ್ತು ಸುಧಾರಿಸುತ್ತಿದ್ದೇವೆ. ಆದ್ದರಿಂದ, ವಿಶ್ಲೇಷಕವು ಹಿಂದಿನ ಸ್ಕ್ಯಾನ್‌ಗಳಲ್ಲಿ ಗಮನಿಸದ ದೋಷಗಳನ್ನು ಗುರುತಿಸಬಹುದು.
  3. 2 ವರ್ಷಗಳ ಹಿಂದೆ ಅಸ್ತಿತ್ವದಲ್ಲಿರದ PVS-ಸ್ಟುಡಿಯೋದಲ್ಲಿ ಹೊಸ ರೋಗನಿರ್ಣಯಗಳು ಕಾಣಿಸಿಕೊಂಡಿವೆ. PVS-ಸ್ಟುಡಿಯೊದ ಅಭಿವೃದ್ಧಿಯನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ತೋರಿಸಲು ಪ್ರತ್ಯೇಕ ವಿಭಾಗದಲ್ಲಿ ಅವುಗಳನ್ನು ಹೈಲೈಟ್ ಮಾಡಲು ನಾನು ನಿರ್ಧರಿಸಿದೆ.

2 ವರ್ಷಗಳ ಹಿಂದೆ ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದ ರೋಗನಿರ್ಣಯದಿಂದ ದೋಷಗಳನ್ನು ಗುರುತಿಸಲಾಗಿದೆ

ತುಣುಕು 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" ಎಂಬ ಸಬ್‌ಸ್ಟ್ರಿಂಗ್‌ನೊಂದಿಗೆ ಹೆಸರು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ ಎಂದು ಎರಡು ಬಾರಿ ಪರಿಶೀಲಿಸಲಾಗಿದೆ. ಎರಡನೇ ಪರಿಶೀಲನೆಯಲ್ಲಿ, ಅವರು ನಿಸ್ಸಂಶಯವಾಗಿ ಬೇರೆ ಏನನ್ನಾದರೂ ಬರೆಯಲು ಬಯಸಿದ್ದರು, ಆದರೆ ನಕಲು ಮಾಡಿದ ಪಠ್ಯವನ್ನು ಸರಿಪಡಿಸಲು ಮರೆತಿದ್ದಾರೆ.

ತುಣುಕು 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_Want Qualifier.

ತುಣುಕು 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().

ದೋಷ ಹ್ಯಾಂಡ್ಲರ್‌ನಲ್ಲಿ ದೋಷವನ್ನು ಮರೆಮಾಡಿದಾಗ ಇದು ಅತ್ಯಂತ ವಿಶಿಷ್ಟವಾದ ಪರಿಸ್ಥಿತಿಯಾಗಿದೆ, ಏಕೆಂದರೆ ಯಾರೂ ಅವುಗಳನ್ನು ಪರೀಕ್ಷಿಸುವುದಿಲ್ಲ. ಸ್ಥಾಯೀ ವಿಶ್ಲೇಷಕರು ಎಲ್ಲಾ ತಲುಪಬಹುದಾದ ಕೋಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸುತ್ತಾರೆ, ಅದನ್ನು ಎಷ್ಟು ಬಾರಿ ಬಳಸಿದರೂ ಪರವಾಗಿಲ್ಲ. ಸ್ಥಾಯೀ ವಿಶ್ಲೇಷಣೆಯು ಇತರ ಪರೀಕ್ಷೆ ಮತ್ತು ದೋಷ ಸಂರಕ್ಷಣಾ ತಂತ್ರಗಳನ್ನು ಹೇಗೆ ಪೂರೈಸುತ್ತದೆ ಎಂಬುದಕ್ಕೆ ಇದು ಉತ್ತಮ ಉದಾಹರಣೆಯಾಗಿದೆ.

ಇದೇ ರೀತಿಯ ಪಾಯಿಂಟರ್ ನಿರ್ವಹಣೆ ದೋಷ ಆರ್ಹೆಚ್ಎಸ್ ಕೆಳಗಿನ ಕೋಡ್‌ನಲ್ಲಿ ಅನುಮತಿಸಲಾಗಿದೆ: V522 [CWE-476] ಶೂನ್ಯ ಪಾಯಿಂಟರ್ 'RHS' ನ ಡಿಫರೆನ್ಸಿಂಗ್ ನಡೆಯಬಹುದು. TGParser.cpp 2186

ತುಣುಕು 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

ಆರಂಭದಲ್ಲಿ ಸ್ಮಾರ್ಟ್ ಪಾಯಿಂಟರ್ ಪ್ರೋಗ್ಕ್ಲೋನ್ ವಸ್ತುವನ್ನು ಹೊಂದುವುದನ್ನು ನಿಲ್ಲಿಸುತ್ತದೆ:

BD.setNewProgram(std::move(ProgClone));

ವಾಸ್ತವವಾಗಿ, ಈಗ ಪ್ರೋಗ್ಕ್ಲೋನ್ ಶೂನ್ಯ ಸೂಚಕವಾಗಿದೆ. ಆದ್ದರಿಂದ, ಶೂನ್ಯ ಪಾಯಿಂಟರ್ ಡಿರೆಫರೆನ್ಸ್ ಕೆಳಗೆ ಸಂಭವಿಸಬೇಕು:

Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first);

ಆದರೆ, ವಾಸ್ತವದಲ್ಲಿ ಇದು ಆಗುವುದಿಲ್ಲ! ಲೂಪ್ ಅನ್ನು ವಾಸ್ತವವಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗಿಲ್ಲ ಎಂಬುದನ್ನು ಗಮನಿಸಿ.

ಕಂಟೇನರ್ ಆರಂಭದಲ್ಲಿ ತಪ್ಪಾಗಿ ಸಂಕಲಿಸಿದ ಕಾರ್ಯಗಳು ತೆರವುಗೊಳಿಸಲಾಗಿದೆ:

MiscompiledFunctions.clear();

ಮುಂದೆ, ಈ ಕಂಟೇನರ್ನ ಗಾತ್ರವನ್ನು ಲೂಪ್ ಸ್ಥಿತಿಯಲ್ಲಿ ಬಳಸಲಾಗುತ್ತದೆ:

for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) {

ಲೂಪ್ ಪ್ರಾರಂಭವಾಗುವುದಿಲ್ಲ ಎಂದು ನೋಡುವುದು ಸುಲಭ. ಇದು ಸಹ ದೋಷವಾಗಿದೆ ಮತ್ತು ಕೋಡ್ ಅನ್ನು ವಿಭಿನ್ನವಾಗಿ ಬರೆಯಬೇಕು ಎಂದು ನಾನು ಭಾವಿಸುತ್ತೇನೆ.

ದೋಷಗಳ ಪ್ರಸಿದ್ಧ ಸಮಾನತೆಯನ್ನು ನಾವು ಎದುರಿಸಿದ್ದೇವೆ ಎಂದು ತೋರುತ್ತದೆ! ಒಂದು ತಪ್ಪು ಇನ್ನೊಂದು ಮರೆಮಾಚುತ್ತದೆ :).

ತುಣುಕು 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

ಎಲ್ಲವೂ ಸ್ಪಷ್ಟವಾಗಿದೆ ಮತ್ತು ವಿವರಣೆಯ ಅಗತ್ಯವಿಲ್ಲ ಎಂದು ನಾನು ಭಾವಿಸುತ್ತೇನೆ.

ತುಣುಕು 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 'ಐಡೆಂಟಿಫೈಯರ್->ಟೈಪ್' ವೇರಿಯೇಬಲ್ ಅನ್ನು ಸ್ವತಃ ನಿಯೋಜಿಸಲಾಗಿದೆ. FormatTokenLexer.cpp 249

ವೇರಿಯಬಲ್ ಅನ್ನು ಸ್ವತಃ ನಿಯೋಜಿಸುವುದರಲ್ಲಿ ಯಾವುದೇ ಅರ್ಥವಿಲ್ಲ. ಹೆಚ್ಚಾಗಿ ಅವರು ಬರೆಯಲು ಬಯಸಿದ್ದರು:

Identifier->Type = Question->Type;

ತುಣುಕು 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

ಪಾಯಿಂಟರ್ ಕ್ಯಾಲೀ ಕಾರ್ಯವನ್ನು ಕರೆಯುವ ಸಮಯದಲ್ಲಿ ಪ್ರಾರಂಭದಲ್ಲಿ ಉಲ್ಲೇಖಿಸಲಾಗಿದೆ getTTI.

ತದನಂತರ ಈ ಪಾಯಿಂಟರ್ ಅನ್ನು ಸಮಾನತೆಗಾಗಿ ಪರಿಶೀಲಿಸಬೇಕು ಎಂದು ಅದು ತಿರುಗುತ್ತದೆ 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] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸುವ ಮೊದಲು 'CalleeFn' ಪಾಯಿಂಟರ್ ಅನ್ನು ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 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] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸುವ ಮೊದಲು 'U' ಪಾಯಿಂಟರ್ ಅನ್ನು ಬಳಸಲಾಯಿತು. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 404, 407. DWARFormValue.cpp 404
  • V595 [CWE-476] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸುವ ಮೊದಲು 'ND' ಪಾಯಿಂಟರ್ ಅನ್ನು ಬಳಸಲಾಯಿತು. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 2149, 2151. SemaTemplateInstantiate.cpp 2149

ತದನಂತರ ನಾನು V595 ಸಂಖ್ಯೆಯೊಂದಿಗೆ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಅಧ್ಯಯನ ಮಾಡಲು ಆಸಕ್ತಿ ಹೊಂದಿಲ್ಲ. ಹಾಗಾಗಿ ಇಲ್ಲಿ ಪಟ್ಟಿ ಮಾಡಲಾದ ದೋಷಗಳ ಹೊರತಾಗಿ ಇನ್ನಷ್ಟು ಇದೇ ರೀತಿಯ ದೋಷಗಳಿವೆಯೇ ಎಂದು ನನಗೆ ತಿಳಿದಿಲ್ಲ. ಹೆಚ್ಚಾಗಿ ಇರುತ್ತದೆ.

ತುಣುಕು 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 ಕ್ಕೆ ಸಮಾನವಾಗಿರುತ್ತದೆ, ಮತ್ತು ನಂತರ ಕೋಡ್ನ ಲೇಖಕರು ಅದನ್ನು ವೇರಿಯೇಬಲ್ನಲ್ಲಿ ಪಡೆಯಲು ಯೋಜಿಸಿದ್ದಾರೆ ನಿಮ್ಸ್ ಮೌಲ್ಯ:

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

ತುಣುಕು 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] ತಂತಿಗಳನ್ನು ಜೋಡಿಸಲಾಗಿದೆ ಆದರೆ ಬಳಸಲಾಗುವುದಿಲ್ಲ. 'ಫಲಿತಾಂಶ + ಹೆಸರು.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

ಆಕಸ್ಮಿಕವಾಗಿ, += ಆಪರೇಟರ್ ಬದಲಿಗೆ + ಆಪರೇಟರ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ. ಫಲಿತಾಂಶವು ಅರ್ಥವಿಲ್ಲದ ವಿನ್ಯಾಸಗಳು.

ತುಣುಕು 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' 'ನಕ್ಷೆ' ವರ್ಗವಾಗಿದೆ. ಇದು ವ್ಯಾಖ್ಯಾನಿಸದ ನಡವಳಿಕೆಗೆ ಕಾರಣವಾಗಬಹುದು. 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

ತುಣುಕು 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

ತುಣುಕು 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

ಪರಿಶೀಲಿಸುವುದರಲ್ಲಿ ಅರ್ಥವಿಲ್ಲ. ವೇರಿಯಬಲ್ ಮುಂದಿನ ಬೈಟ್ ಯಾವಾಗಲೂ ಮೌಲ್ಯಕ್ಕೆ ಸಮನಾಗಿರುವುದಿಲ್ಲ 0x90, ಇದು ಹಿಂದಿನ ಚೆಕ್‌ನಿಂದ ಅನುಸರಿಸುತ್ತದೆ. ಇದು ಕೆಲವು ರೀತಿಯ ತಾರ್ಕಿಕ ದೋಷವಾಗಿದೆ.

ತುಣುಕು 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, ನಂತರ ಕಾರ್ಯವು ಅದರ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸುತ್ತದೆ.

V547 ಮತ್ತು V560 ID ಗಳೊಂದಿಗೆ ಅನೇಕ ಇತರ ಎಚ್ಚರಿಕೆಗಳು ಇದ್ದವು, ಆದರೆ ಹಾಗೆ V595, ಈ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಅಧ್ಯಯನ ಮಾಡಲು ನನಗೆ ಆಸಕ್ತಿ ಇರಲಿಲ್ಲ. ಲೇಖನವನ್ನು ಬರೆಯಲು ನನ್ನ ಬಳಿ ಸಾಕಷ್ಟು ವಸ್ತುವಿದೆ ಎಂದು ಈಗಾಗಲೇ ಸ್ಪಷ್ಟವಾಗಿದೆ :). ಆದ್ದರಿಂದ, PVS-Studio ಅನ್ನು ಬಳಸಿಕೊಂಡು 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

ತುಣುಕು 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 ಸಾಮಾನ್ಯ ಉದ್ದೇಶದ ರೋಗನಿರ್ಣಯವನ್ನು ಸೇರಿಸಲಾಯಿತು.

ತುಣುಕು 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 ಆಪರೇಟರ್‌ಗೆ ಕರೆಯೊಂದಿಗೆ ಕೊನೆಗೊಳ್ಳುತ್ತದೆ ರಿಟರ್ನ್. ಅದರಂತೆ, ಕಂಟೇನರ್ ಆದ್ಯತೆಯ ಮೂಲಕ CtorDtors ಎಂದಿಗೂ ತೆರವುಗೊಳಿಸಲಾಗುವುದಿಲ್ಲ.

ತುಣುಕು 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;

ಮತ್ತು ವಾಸ್ತವವಾಗಿ, ಈ ಕೋಡ್ ಅನ್ನು ತಲುಪಲಾಗುವುದಿಲ್ಲ. ಎಲ್ಲಾ ಪ್ರಕರಣಗಳಲ್ಲಿ ಸ್ವಿಚ್ ಆಪರೇಟರ್‌ನಿಂದ ಕರೆಯೊಂದಿಗೆ ಕೊನೆಗೊಳ್ಳುತ್ತದೆ ರಿಟರ್ನ್. ಮತ್ತು ಈಗ ಏಕಾಂಗಿಯಾಗಿ ಪ್ರಜ್ಞಾಶೂನ್ಯ ಬ್ರೇಕ್ ಅಷ್ಟು ನಿರುಪದ್ರವವಾಗಿ ಕಾಣುತ್ತಿಲ್ಲ! ಬಹುಶಃ ಶಾಖೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಕೊನೆಗೊಳಿಸಬೇಕು ಬ್ರೇಕ್ಆನ್ ಆಗಿಲ್ಲ ರಿಟರ್ನ್?

ತುಣುಕು 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

ಕಾರ್ಯವನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ ಪಡೆಯಿರಿ ಸ್ಟಬ್ಅಲೈನ್ಮೆಂಟ್ ಹಿಂತಿರುಗಿಸುವ ಪ್ರಕಾರ ಸಹಿ ಮಾಡಲಾಗಿಲ್ಲ. ಕ್ರಿಯೆಯು ಮೌಲ್ಯ 8 ಅನ್ನು ಹಿಂದಿರುಗಿಸುತ್ತದೆ ಎಂದು ಭಾವಿಸಿ, ಅಭಿವ್ಯಕ್ತಿಯ ಮೌಲ್ಯವನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡೋಣ:

~(getStubAlignment() - 1)

~(8u-1)

0xFFFFFFFF8u

ಈಗ ವೇರಿಯಬಲ್ ಗಮನಿಸಿ ಡೇಟಾ ಗಾತ್ರ 64-ಬಿಟ್ ಸಹಿ ಮಾಡದ ಪ್ರಕಾರವನ್ನು ಹೊಂದಿದೆ. DataSize & 0xFFFFFFF8u ಕಾರ್ಯಾಚರಣೆಯನ್ನು ನಿರ್ವಹಿಸುವಾಗ, ಎಲ್ಲಾ ಮೂವತ್ತೆರಡು ಉನ್ನತ-ಆರ್ಡರ್ ಬಿಟ್‌ಗಳನ್ನು ಶೂನ್ಯಕ್ಕೆ ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ ಎಂದು ಅದು ತಿರುಗುತ್ತದೆ. ಹೆಚ್ಚಾಗಿ, ಇದು ಪ್ರೋಗ್ರಾಮರ್ ಬಯಸಿದ್ದಲ್ಲ. ಅವರು ಲೆಕ್ಕಾಚಾರ ಮಾಡಲು ಬಯಸಿದ್ದಾರೆ ಎಂದು ನಾನು ಅನುಮಾನಿಸುತ್ತೇನೆ: ಡೇಟಾಸೈಜ್ & 0xFFFFFFFFFFFFFFF8u.

ದೋಷವನ್ನು ಸರಿಪಡಿಸಲು, ನೀವು ಇದನ್ನು ಬರೆಯಬೇಕು:

DataSize &= ~(static_cast<uint64_t>(getStubAlignment()) - 1);

ಅಥವಾ ಹೀಗೆ:

DataSize &= ~(getStubAlignment() - 1ULL);

ತುಣುಕು 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 * ಸ್ಕೇಲ್' ಆಪರೇಟರ್‌ನ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು 'size_t' ಪ್ರಕಾರಕ್ಕೆ ಬಿತ್ತರಿಸುವುದನ್ನು ಪರಿಗಣಿಸಿ, ಫಲಿತಾಂಶವಲ್ಲ. X86ISelLowering.h 1577

ವಿಧದ ವೇರಿಯೇಬಲ್‌ಗಳನ್ನು ಗುಣಿಸುವಾಗ ಓವರ್‌ಫ್ಲೋ ತಪ್ಪಿಸಲು ಸ್ಪಷ್ಟ ಪ್ರಕಾರದ ಎರಕವನ್ನು ಬಳಸಲಾಗುತ್ತದೆ ಇಂಟ್. ಆದಾಗ್ಯೂ, ಇಲ್ಲಿ ಸ್ಪಷ್ಟ ಪ್ರಕಾರದ ಎರಕಹೊಯ್ದವು ಓವರ್‌ಫ್ಲೋ ವಿರುದ್ಧ ರಕ್ಷಿಸುವುದಿಲ್ಲ. ಮೊದಲಿಗೆ, ಅಸ್ಥಿರಗಳನ್ನು ಗುಣಿಸಲಾಗುತ್ತದೆ, ಮತ್ತು ನಂತರ ಮಾತ್ರ ಗುಣಾಕಾರದ 32-ಬಿಟ್ ಫಲಿತಾಂಶವನ್ನು ಪ್ರಕಾರಕ್ಕೆ ವಿಸ್ತರಿಸಲಾಗುತ್ತದೆ ಗಾತ್ರ_ಟಿ.

ತುಣುಕು 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

ಈ ಹೊಸ ಆಸಕ್ತಿದಾಯಕ ರೋಗನಿರ್ಣಯವು ಕೋಡ್‌ನ ತುಣುಕನ್ನು ನಕಲಿಸಿರುವ ಸಂದರ್ಭಗಳನ್ನು ಗುರುತಿಸುತ್ತದೆ ಮತ್ತು ಅದರಲ್ಲಿ ಕೆಲವು ಹೆಸರುಗಳನ್ನು ಬದಲಾಯಿಸಲು ಪ್ರಾರಂಭಿಸಲಾಗಿದೆ, ಆದರೆ ಒಂದು ಸ್ಥಳದಲ್ಲಿ ಅವರು ಅದನ್ನು ಸರಿಪಡಿಸಿಲ್ಲ.

ಎರಡನೇ ಬ್ಲಾಕ್ನಲ್ಲಿ ಅವರು ಬದಲಾಗಿದ್ದಾರೆ ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ ಆಪ್ 0 ಮೇಲೆ ಆಪ್ 1. ಆದರೆ ಒಂದು ಸ್ಥಳದಲ್ಲಿ ಅವರು ಅದನ್ನು ಸರಿಪಡಿಸಲಿಲ್ಲ. ಹೆಚ್ಚಾಗಿ ಇದನ್ನು ಈ ರೀತಿ ಬರೆಯಬೇಕು:

if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1, &TLI)) {
  I.setOperand(1, ConstantFP::getNullValue(Op1->getType()));
  return &I;
}

ತುಣುಕು 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;
};

ತುಣುಕು 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;

ತುಣುಕು 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] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'Ptr' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 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] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'FD' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 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] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'PtrTy' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 960, 965. InterleavedLoadCombinePass.cpp 965

ಅಂತಹ ದೋಷಗಳಿಂದ ನಿಮ್ಮನ್ನು ಹೇಗೆ ರಕ್ಷಿಸಿಕೊಳ್ಳುವುದು? ಕೋಡ್-ರಿವ್ಯೂನಲ್ಲಿ ಹೆಚ್ಚು ಜಾಗರೂಕರಾಗಿರಿ ಮತ್ತು ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು ನಿಯಮಿತವಾಗಿ ಪರಿಶೀಲಿಸಲು PVS-ಸ್ಟುಡಿಯೋ ಸ್ಟ್ಯಾಟಿಕ್ ವಿಶ್ಲೇಷಕವನ್ನು ಬಳಸಿ.

ಈ ಪ್ರಕಾರದ ದೋಷಗಳೊಂದಿಗೆ ಇತರ ಕೋಡ್ ತುಣುಕುಗಳನ್ನು ಉಲ್ಲೇಖಿಸುವುದರಲ್ಲಿ ಯಾವುದೇ ಅರ್ಥವಿಲ್ಲ. ನಾನು ಲೇಖನದಲ್ಲಿ ಎಚ್ಚರಿಕೆಗಳ ಪಟ್ಟಿಯನ್ನು ಮಾತ್ರ ಬಿಡುತ್ತೇನೆ:

  • V1004 [CWE-476] 'Expr' ಪಾಯಿಂಟರ್ ಅನ್ನು nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 1049, 1078. DebugInfoMetadata.cpp 1078
  • V1004 [CWE-476] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'PI' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 733, 753. LegacyPassManager.cpp 753
  • V1004 [CWE-476] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'StatepointCall' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 4371, 4379. Verifier.cpp 4379
  • V1004 [CWE-476] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'RV' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 2263, 2268. TGParser.cpp 2268
  • V1004 [CWE-476] 'CalleeFn' ಪಾಯಿಂಟರ್ ಅನ್ನು nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಸಾಲುಗಳನ್ನು ಪರಿಶೀಲಿಸಿ: 1081, 1096. SimplifyLibCalls.cpp 1096
  • V1004 [CWE-476] nullptr ವಿರುದ್ಧ ಪರಿಶೀಲಿಸಿದ ನಂತರ 'TC' ಪಾಯಿಂಟರ್ ಅನ್ನು ಅಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಲಾಗಿದೆ. ಚೆಕ್ ಲೈನ್‌ಗಳು: 1819, 1824. Driver.cpp 1824

ತುಣುಕು 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] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಸ್ಟ್ರಾಟಜೀಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-isel-fuzzer.cpp 58

ನಂತಹ ಕಂಟೇನರ್‌ನ ಅಂತ್ಯಕ್ಕೆ ಒಂದು ಅಂಶವನ್ನು ಸೇರಿಸಲು ಎಸ್ಟಿಡಿ:: ವೆಕ್ಟರ್ > ನೀವು ಕೇವಲ ಬರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ xxx.push_back(ಹೊಸ X), ರಿಂದ ಯಾವುದೇ ಸೂಚ್ಯ ಪರಿವರ್ತನೆ ಇಲ್ಲ X* в std::unique_ptr.

ಸಾಮಾನ್ಯ ಪರಿಹಾರವೆಂದರೆ ಬರೆಯುವುದು xxx.emplace_back(ಹೊಸ X)ಇದು ಕಂಪೈಲ್ ಆಗಿರುವುದರಿಂದ: ವಿಧಾನ 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] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಮ್‌ಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'AAs' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. AliasAnalysis.h 324
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಎಂಟ್ರಿಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. DWARFDebugFrame.cpp 519
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'Emplace_back' ವಿಧಾನದ ಮೂಲಕ 'AllEdges' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. CFGMST.h 268
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'VMaps' ಕಂಟೇನರ್‌ಗೆ 'emplace_back' ವಿಧಾನದಿಂದ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. SimpleLoopUnswitch.cpp 2012
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ರೆಕಾರ್ಡ್ಸ್' ಕಂಟೇನರ್‌ಗೆ 'emplace_back' ವಿಧಾನದಿಂದ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. FDRLogBuilder.h 30
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಪೆಂಡಿಂಗ್‌ಸಬ್ ಮಾಡ್ಯೂಲ್‌ಗಳು' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. ModuleMap.cpp 810
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಆಬ್ಜೆಕ್ಟ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. DebugMap.cpp 88
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಸ್ಟ್ರಾಟಜೀಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-isel-fuzzer.cpp 60
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 685
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 686
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 688
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 689
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 690
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 691
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 692
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 693
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮಾಡಿಫೈಯರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. llvm-stress.cpp 694
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಒಪೆರಾಂಡ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. GlobalISelEmitter.cpp 1911
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'Emplace_back' ವಿಧಾನದ ಮೂಲಕ 'Stash' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. GlobalISelEmitter.cpp 2100
  • V1023 [CWE-460] ಮಾಲೀಕರಿಲ್ಲದ ಪಾಯಿಂಟರ್ ಅನ್ನು 'ಎಂಪ್ಲೇಸ್_ಬ್ಯಾಕ್' ವಿಧಾನದ ಮೂಲಕ 'ಮ್ಯಾಚರ್ಸ್' ಕಂಟೇನರ್‌ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ. ವಿನಾಯಿತಿಯ ಸಂದರ್ಭದಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆ ಸಂಭವಿಸುತ್ತದೆ. GlobalISelEmitter.cpp 2702

ತೀರ್ಮಾನಕ್ಕೆ

ನಾನು ಒಟ್ಟು 60 ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೀಡಿದ್ದೇನೆ ಮತ್ತು ನಂತರ ನಿಲ್ಲಿಸಿದೆ. LLVM ನಲ್ಲಿ PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವು ಪತ್ತೆಹಚ್ಚುವ ಇತರ ದೋಷಗಳಿವೆಯೇ? ಹೌದು ನನ್ನೊಂದಿಗಿದೆ. ಆದಾಗ್ಯೂ, ನಾನು ಲೇಖನಕ್ಕಾಗಿ ಕೋಡ್ ತುಣುಕುಗಳನ್ನು ಬರೆಯುವಾಗ, ಅದು ತಡವಾಗಿ ಸಂಜೆ ಅಥವಾ ರಾತ್ರಿಯೂ ಆಗಿತ್ತು, ಮತ್ತು ಅದನ್ನು ಒಂದು ದಿನ ಎಂದು ಕರೆಯುವ ಸಮಯ ಎಂದು ನಾನು ನಿರ್ಧರಿಸಿದೆ.

ನೀವು ಇದನ್ನು ಆಸಕ್ತಿದಾಯಕವೆಂದು ಭಾವಿಸುತ್ತೇನೆ ಮತ್ತು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವನ್ನು ಪ್ರಯತ್ನಿಸಲು ಬಯಸುತ್ತೀರಿ.

ನೀವು ವಿಶ್ಲೇಷಕವನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಬಹುದು ಮತ್ತು ಮೈನ್‌ಸ್ವೀಪರ್ ಕೀಲಿಯನ್ನು ಇಲ್ಲಿ ಪಡೆಯಬಹುದು ಈ ಪುಟ.

ಬಹು ಮುಖ್ಯವಾಗಿ, ಸ್ಥಿರ ವಿಶ್ಲೇಷಣೆಯನ್ನು ನಿಯಮಿತವಾಗಿ ಬಳಸಿ. ಒಂದು ಬಾರಿ ತಪಾಸಣೆ, ಸ್ಥಿರ ವಿಶ್ಲೇಷಣೆಯ ವಿಧಾನವನ್ನು ಜನಪ್ರಿಯಗೊಳಿಸುವ ಸಲುವಾಗಿ ನಮ್ಮಿಂದ ನಡೆಸಲ್ಪಟ್ಟಿದೆ ಮತ್ತು PVS-ಸ್ಟುಡಿಯೋ ಸಾಮಾನ್ಯ ಸನ್ನಿವೇಶವಲ್ಲ.

ನಿಮ್ಮ ಕೋಡ್‌ನ ಗುಣಮಟ್ಟ ಮತ್ತು ವಿಶ್ವಾಸಾರ್ಹತೆಯನ್ನು ಸುಧಾರಿಸುವಲ್ಲಿ ಅದೃಷ್ಟ!

PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವನ್ನು ಬಳಸಿಕೊಂಡು LLVM 8 ರಲ್ಲಿ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯುವುದು

ನೀವು ಈ ಲೇಖನವನ್ನು ಇಂಗ್ಲಿಷ್ ಮಾತನಾಡುವ ಪ್ರೇಕ್ಷಕರೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಲು ಬಯಸಿದರೆ, ದಯವಿಟ್ಟು ಅನುವಾದ ಲಿಂಕ್ ಬಳಸಿ: ಆಂಡ್ರೆ ಕಾರ್ಪೋವ್. PVS-ಸ್ಟುಡಿಯೊದೊಂದಿಗೆ LLVM 8 ರಲ್ಲಿ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯುವುದು.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ