ನಮ್ಮ PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವನ್ನು ಬಳಸಿಕೊಂಡು LLVM ಯೋಜನೆಯ ಕೊನೆಯ ಕೋಡ್ ಪರಿಶೀಲನೆಯಿಂದ ಎರಡು ವರ್ಷಗಳು ಕಳೆದಿವೆ. ದೋಷಗಳು ಮತ್ತು ಸಂಭಾವ್ಯ ದುರ್ಬಲತೆಗಳನ್ನು ಗುರುತಿಸಲು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕವು ಇನ್ನೂ ಪ್ರಮುಖ ಸಾಧನವಾಗಿದೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳೋಣ. ಇದನ್ನು ಮಾಡಲು, ನಾವು LLVM 8.0.0 ಬಿಡುಗಡೆಯಲ್ಲಿ ಹೊಸ ದೋಷಗಳನ್ನು ಪರಿಶೀಲಿಸುತ್ತೇವೆ ಮತ್ತು ಕಂಡುಹಿಡಿಯುತ್ತೇವೆ.
ಬರೆಯಬೇಕಾದ ಲೇಖನ
ನಿಜ ಹೇಳಬೇಕೆಂದರೆ, ನಾನು ಈ ಲೇಖನವನ್ನು ಬರೆಯಲು ಬಯಸಲಿಲ್ಲ. ನಾವು ಈಗಾಗಲೇ ಹಲವಾರು ಬಾರಿ ಪರಿಶೀಲಿಸಿದ ಯೋಜನೆಯ ಬಗ್ಗೆ ಬರೆಯುವುದು ಆಸಕ್ತಿದಾಯಕವಲ್ಲ (
ಪ್ರತಿ ಬಾರಿ LLVM ನ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲಾಗುತ್ತದೆ ಅಥವಾ ನವೀಕರಿಸಲಾಗುತ್ತದೆ
ನೋಡಿ, ಕ್ಲಾಂಗ್ ಸ್ಟ್ಯಾಟಿಕ್ ವಿಶ್ಲೇಷಕದ ಹೊಸ ಆವೃತ್ತಿಯು ಹೊಸ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಕಲಿತಿದೆ! PVS-Studio ಅನ್ನು ಬಳಸುವ ಪ್ರಸ್ತುತತೆ ಕಡಿಮೆಯಾಗುತ್ತಿದೆ ಎಂದು ನನಗೆ ತೋರುತ್ತದೆ. ಕ್ಲಾಂಗ್ ಮೊದಲಿಗಿಂತ ಹೆಚ್ಚು ದೋಷಗಳನ್ನು ಕಂಡುಕೊಳ್ಳುತ್ತದೆ ಮತ್ತು PVS-ಸ್ಟುಡಿಯೊದ ಸಾಮರ್ಥ್ಯಗಳೊಂದಿಗೆ ಹಿಡಿಯುತ್ತದೆ. ನೀವು ಇದರ ಬಗ್ಗೆ ಏನನ್ನು ಯೋಚಿಸುತ್ತಿರಿ?
ಇದಕ್ಕೆ ನಾನು ಯಾವಾಗಲೂ ಉತ್ತರಿಸಲು ಬಯಸುತ್ತೇನೆ:
ನಾವೂ ಸುಮ್ಮನೆ ಕೂರುವುದಿಲ್ಲ! PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕದ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ನಾವು ಗಮನಾರ್ಹವಾಗಿ ಸುಧಾರಿಸಿದ್ದೇವೆ. ಆದ್ದರಿಂದ ಚಿಂತಿಸಬೇಡಿ, ನಾವು ಮೊದಲಿನಂತೆಯೇ ಮುನ್ನಡೆಯುತ್ತೇವೆ.
ದುರದೃಷ್ಟವಶಾತ್, ಇದು ಕೆಟ್ಟ ಉತ್ತರವಾಗಿದೆ. ಅದರಲ್ಲಿ ಯಾವುದೇ ಪುರಾವೆಗಳಿಲ್ಲ. ಮತ್ತು ಅದಕ್ಕಾಗಿಯೇ ನಾನು ಈಗ ಈ ಲೇಖನವನ್ನು ಬರೆಯುತ್ತಿದ್ದೇನೆ. ಆದ್ದರಿಂದ, LLVM ಯೋಜನೆಯನ್ನು ಮತ್ತೊಮ್ಮೆ ಪರಿಶೀಲಿಸಲಾಗಿದೆ ಮತ್ತು ಅದರಲ್ಲಿ ವಿವಿಧ ದೋಷಗಳು ಕಂಡುಬಂದಿವೆ. ನನಗೆ ಆಸಕ್ತಿದಾಯಕವೆಂದು ತೋರುವದನ್ನು ನಾನು ಈಗ ಪ್ರದರ್ಶಿಸುತ್ತೇನೆ. ಕ್ಲಾಂಗ್ ಸ್ಟ್ಯಾಟಿಕ್ ವಿಶ್ಲೇಷಕವು ಈ ದೋಷಗಳನ್ನು ಕಂಡುಹಿಡಿಯಲು ಸಾಧ್ಯವಿಲ್ಲ (ಅಥವಾ ಅದರ ಸಹಾಯದಿಂದ ಹಾಗೆ ಮಾಡುವುದು ಅತ್ಯಂತ ಅನಾನುಕೂಲವಾಗಿದೆ). ಆದರೆ ನಾವು ಮಾಡಬಹುದು. ಇದಲ್ಲದೆ, ನಾನು ಈ ಎಲ್ಲಾ ದೋಷಗಳನ್ನು ಒಂದೇ ಸಂಜೆಯಲ್ಲಿ ಕಂಡುಕೊಂಡೆ ಮತ್ತು ಬರೆದಿದ್ದೇನೆ.
ಆದರೆ ಲೇಖನವನ್ನು ಬರೆಯಲು ಹಲವಾರು ವಾರಗಳನ್ನು ತೆಗೆದುಕೊಂಡಿತು. ಇದನ್ನೆಲ್ಲ ಪಠ್ಯಕ್ಕೆ ಹಾಕಲು ನನಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ :).
ಮೂಲಕ, ದೋಷಗಳು ಮತ್ತು ಸಂಭಾವ್ಯ ದುರ್ಬಲತೆಗಳನ್ನು ಗುರುತಿಸಲು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕದಲ್ಲಿ ಯಾವ ತಂತ್ರಜ್ಞಾನಗಳನ್ನು ಬಳಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಬಗ್ಗೆ ನೀವು ಆಸಕ್ತಿ ಹೊಂದಿದ್ದರೆ, ನಂತರ ನಾನು ಇದರೊಂದಿಗೆ ಪರಿಚಯ ಮಾಡಿಕೊಳ್ಳಲು ಸಲಹೆ ನೀಡುತ್ತೇನೆ.
ಹೊಸ ಮತ್ತು ಹಳೆಯ ರೋಗನಿರ್ಣಯ
ಈಗಾಗಲೇ ಗಮನಿಸಿದಂತೆ, ಸುಮಾರು ಎರಡು ವರ್ಷಗಳ ಹಿಂದೆ LLVM ಯೋಜನೆಯನ್ನು ಮತ್ತೊಮ್ಮೆ ಪರಿಶೀಲಿಸಲಾಯಿತು, ಮತ್ತು ಕಂಡುಬಂದ ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸಲಾಗಿದೆ. ಈಗ ಈ ಲೇಖನವು ದೋಷಗಳ ಹೊಸ ಬ್ಯಾಚ್ ಅನ್ನು ಪ್ರಸ್ತುತಪಡಿಸುತ್ತದೆ. ಹೊಸ ದೋಷಗಳು ಏಕೆ ಕಂಡುಬಂದಿವೆ? ಇದಕ್ಕೆ 3 ಕಾರಣಗಳಿವೆ:
- LLVM ಯೋಜನೆಯು ವಿಕಸನಗೊಳ್ಳುತ್ತಿದೆ, ಹಳೆಯ ಕೋಡ್ ಅನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ ಮತ್ತು ಹೊಸ ಕೋಡ್ ಅನ್ನು ಸೇರಿಸುತ್ತದೆ. ಸ್ವಾಭಾವಿಕವಾಗಿ, ಮಾರ್ಪಡಿಸಿದ ಮತ್ತು ಲಿಖಿತ ಕೋಡ್ನಲ್ಲಿ ಹೊಸ ದೋಷಗಳಿವೆ. ಸ್ಥಿರ ವಿಶ್ಲೇಷಣೆಯನ್ನು ನಿಯಮಿತವಾಗಿ ಬಳಸಬೇಕು ಮತ್ತು ಸಾಂದರ್ಭಿಕವಾಗಿ ಬಳಸಬಾರದು ಎಂದು ಇದು ಸ್ಪಷ್ಟವಾಗಿ ತೋರಿಸುತ್ತದೆ. ನಮ್ಮ ಲೇಖನಗಳು PVS-ಸ್ಟುಡಿಯೋ ವಿಶ್ಲೇಷಕದ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಚೆನ್ನಾಗಿ ತೋರಿಸುತ್ತವೆ, ಆದರೆ ಇದು ಕೋಡ್ ಗುಣಮಟ್ಟವನ್ನು ಸುಧಾರಿಸಲು ಮತ್ತು ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸುವ ವೆಚ್ಚವನ್ನು ಕಡಿಮೆ ಮಾಡಲು ಏನೂ ಹೊಂದಿಲ್ಲ. ಸ್ಥಿರ ಕೋಡ್ ವಿಶ್ಲೇಷಕವನ್ನು ನಿಯಮಿತವಾಗಿ ಬಳಸಿ!
- ನಾವು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ರೋಗನಿರ್ಣಯವನ್ನು ಅಂತಿಮಗೊಳಿಸುತ್ತಿದ್ದೇವೆ ಮತ್ತು ಸುಧಾರಿಸುತ್ತಿದ್ದೇವೆ. ಆದ್ದರಿಂದ, ವಿಶ್ಲೇಷಕವು ಹಿಂದಿನ ಸ್ಕ್ಯಾನ್ಗಳಲ್ಲಿ ಗಮನಿಸದ ದೋಷಗಳನ್ನು ಗುರುತಿಸಬಹುದು.
- 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
"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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ನನ್ನ ಅಭಿಪ್ರಾಯದಲ್ಲಿ, ಇದು ತುಂಬಾ ಸುಂದರವಾದ ತಪ್ಪು. ಹೌದು, ನನಗೆ ಸೌಂದರ್ಯದ ಬಗ್ಗೆ ವಿಚಿತ್ರವಾದ ವಿಚಾರಗಳಿವೆ ಎಂದು ನನಗೆ ತಿಳಿದಿದೆ :).
ಈಗ, ಪ್ರಕಾರ
(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().
ದೋಷ ಹ್ಯಾಂಡ್ಲರ್ನಲ್ಲಿ ದೋಷವನ್ನು ಮರೆಮಾಡಿದಾಗ ಇದು ಅತ್ಯಂತ ವಿಶಿಷ್ಟವಾದ ಪರಿಸ್ಥಿತಿಯಾಗಿದೆ, ಏಕೆಂದರೆ ಯಾರೂ ಅವುಗಳನ್ನು ಪರೀಕ್ಷಿಸುವುದಿಲ್ಲ. ಸ್ಥಾಯೀ ವಿಶ್ಲೇಷಕರು ಎಲ್ಲಾ ತಲುಪಬಹುದಾದ ಕೋಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸುತ್ತಾರೆ, ಅದನ್ನು ಎಷ್ಟು ಬಾರಿ ಬಳಸಿದರೂ ಪರವಾಗಿಲ್ಲ. ಸ್ಥಾಯೀ ವಿಶ್ಲೇಷಣೆಯು ಇತರ ಪರೀಕ್ಷೆ ಮತ್ತು ದೋಷ ಸಂರಕ್ಷಣಾ ತಂತ್ರಗಳನ್ನು ಹೇಗೆ ಪೂರೈಸುತ್ತದೆ ಎಂಬುದಕ್ಕೆ ಇದು ಉತ್ತಮ ಉದಾಹರಣೆಯಾಗಿದೆ.
ಇದೇ ರೀತಿಯ ಪಾಯಿಂಟರ್ ನಿರ್ವಹಣೆ ದೋಷ ಆರ್ಹೆಚ್ಎಸ್ ಕೆಳಗಿನ ಕೋಡ್ನಲ್ಲಿ ಅನುಮತಿಸಲಾಗಿದೆ: 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ವೇರಿಯಬಲ್ ಅನ್ನು ಸ್ವತಃ ನಿಯೋಜಿಸುವುದರಲ್ಲಿ ಯಾವುದೇ ಅರ್ಥವಿಲ್ಲ. ಹೆಚ್ಚಾಗಿ ಅವರು ಬರೆಯಲು ಬಯಸಿದ್ದರು:
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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಆರಂಭದಲ್ಲಿ ತುಂಬಾ ಅನುಮಾನಾಸ್ಪದ ಆಪರೇಟರ್ ಇದೆ ಬ್ರೇಕ್. ಇಲ್ಲಿ ಬೇರೇನಾದರೂ ಬರೆಯಲು ಮರೆತಿದ್ದೀರಾ?
ತುಣುಕು 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಪಾಯಿಂಟರ್ ಕ್ಯಾಲೀ ಕಾರ್ಯವನ್ನು ಕರೆಯುವ ಸಮಯದಲ್ಲಿ ಪ್ರಾರಂಭದಲ್ಲಿ ಉಲ್ಲೇಖಿಸಲಾಗಿದೆ 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಇದು ದೋಷವಾಗಿರದೇ ಇರಬಹುದು ಮತ್ತು ಕೋಡ್ ಉದ್ದೇಶಿಸಿದಂತೆ ನಿಖರವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಆದರೆ ಇದು ಸ್ಪಷ್ಟವಾಗಿ ಅತ್ಯಂತ ಅನುಮಾನಾಸ್ಪದ ಸ್ಥಳವಾಗಿದೆ ಮತ್ತು ಪರಿಶೀಲಿಸಬೇಕಾಗಿದೆ.
ವೇರಿಯಬಲ್ ಅನ್ನು ಹೇಳೋಣ ಗಾತ್ರ 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಇಲ್ಲಿ ಯಾವುದೇ ತಪ್ಪಿಲ್ಲ. ಮೊದಲನೆಯ ನಂತರ-ಬ್ಲಾಕ್ ರಿಂದ 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಸಮಸ್ಯೆ ಸಾಲು:
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
ತುಣುಕು 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಪರಿಶೀಲಿಸುವುದರಲ್ಲಿ ಅರ್ಥವಿಲ್ಲ. ವೇರಿಯಬಲ್ ಮುಂದಿನ ಬೈಟ್ ಯಾವಾಗಲೂ ಮೌಲ್ಯಕ್ಕೆ ಸಮನಾಗಿರುವುದಿಲ್ಲ 0x90, ಇದು ಹಿಂದಿನ ಚೆಕ್ನಿಂದ ಅನುಸರಿಸುತ್ತದೆ. ಇದು ಕೆಲವು ರೀತಿಯ ತಾರ್ಕಿಕ ದೋಷವಾಗಿದೆ.
ತುಣುಕು 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, ನಂತರ ಕಾರ್ಯವು ಅದರ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸುತ್ತದೆ.
V547 ಮತ್ತು V560 ID ಗಳೊಂದಿಗೆ ಅನೇಕ ಇತರ ಎಚ್ಚರಿಕೆಗಳು ಇದ್ದವು, ಆದರೆ ಹಾಗೆ
ಈ ಪ್ರಚೋದಕಗಳನ್ನು ಅಧ್ಯಯನ ಮಾಡುವುದು ಏಕೆ ನೀರಸವಾಗಿದೆ ಎಂಬುದಕ್ಕೆ ನಾನು ನಿಮಗೆ ಉದಾಹರಣೆ ನೀಡುತ್ತೇನೆ. ಈ ಕೆಳಗಿನ ಕೋಡ್ಗೆ ಎಚ್ಚರಿಕೆಯನ್ನು ನೀಡುವಲ್ಲಿ ವಿಶ್ಲೇಷಕವು ಸಂಪೂರ್ಣವಾಗಿ ಸರಿಯಾಗಿದೆ. ಆದರೆ ಇದು ತಪ್ಪಲ್ಲ.
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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಇದು ದೋಷ ಅಥವಾ ನಿರ್ದಿಷ್ಟ ತಂತ್ರವಾಗಿದ್ದು, ಕೋಡ್ ಅನ್ನು ಓದುವ ಪ್ರೋಗ್ರಾಮರ್ಗಳಿಗೆ ಏನನ್ನಾದರೂ ವಿವರಿಸಲು ಉದ್ದೇಶಿಸಲಾಗಿದೆ. ಈ ವಿನ್ಯಾಸವು ನನಗೆ ಏನನ್ನೂ ವಿವರಿಸುವುದಿಲ್ಲ ಮತ್ತು ತುಂಬಾ ಅನುಮಾನಾಸ್ಪದವಾಗಿ ಕಾಣುತ್ತದೆ. ಹಾಗೆ ಬರೆಯದಿರುವುದು ಉತ್ತಮ :).
ಸುಸ್ತಾಗಿದೆಯೇ? ನಂತರ ಚಹಾ ಅಥವಾ ಕಾಫಿ ಮಾಡುವ ಸಮಯ.
ಹೊಸ ರೋಗನಿರ್ಣಯದಿಂದ ದೋಷಗಳನ್ನು ಗುರುತಿಸಲಾಗಿದೆ
ಹಳೆಯ ರೋಗನಿರ್ಣಯದ 30 ಸಕ್ರಿಯಗೊಳಿಸುವಿಕೆಗಳು ಸಾಕು ಎಂದು ನಾನು ಭಾವಿಸುತ್ತೇನೆ. ನಂತರ ವಿಶ್ಲೇಷಕದಲ್ಲಿ ಕಾಣಿಸಿಕೊಂಡ ಹೊಸ ಡಯಾಗ್ನೋಸ್ಟಿಕ್ಸ್ನೊಂದಿಗೆ ಯಾವ ಆಸಕ್ತಿದಾಯಕ ವಿಷಯಗಳನ್ನು ಕಂಡುಹಿಡಿಯಬಹುದು ಎಂಬುದನ್ನು ಈಗ ನೋಡೋಣ
ತುಣುಕು 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 ಆಪರೇಟರ್ಗೆ ಕರೆಯೊಂದಿಗೆ ಕೊನೆಗೊಳ್ಳುತ್ತದೆ ರಿಟರ್ನ್. ಅದರಂತೆ, ಕಂಟೇನರ್ ಆದ್ಯತೆಯ ಮೂಲಕ 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ಕಾರ್ಯವನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ ಪಡೆಯಿರಿ ಸ್ಟಬ್ಅಲೈನ್ಮೆಂಟ್ ಹಿಂತಿರುಗಿಸುವ ಪ್ರಕಾರ ಸಹಿ ಮಾಡಲಾಗಿಲ್ಲ. ಕ್ರಿಯೆಯು ಮೌಲ್ಯ 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ವಿಧದ ವೇರಿಯೇಬಲ್ಗಳನ್ನು ಗುಣಿಸುವಾಗ ಓವರ್ಫ್ಲೋ ತಪ್ಪಿಸಲು ಸ್ಪಷ್ಟ ಪ್ರಕಾರದ ಎರಕವನ್ನು ಬಳಸಲಾಗುತ್ತದೆ ಇಂಟ್. ಆದಾಗ್ಯೂ, ಇಲ್ಲಿ ಸ್ಪಷ್ಟ ಪ್ರಕಾರದ ಎರಕಹೊಯ್ದವು ಓವರ್ಫ್ಲೋ ವಿರುದ್ಧ ರಕ್ಷಿಸುವುದಿಲ್ಲ. ಮೊದಲಿಗೆ, ಅಸ್ಥಿರಗಳನ್ನು ಗುಣಿಸಲಾಗುತ್ತದೆ, ಮತ್ತು ನಂತರ ಮಾತ್ರ ಗುಣಾಕಾರದ 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;
}
....
}
ಈ ಹೊಸ ಆಸಕ್ತಿದಾಯಕ ರೋಗನಿರ್ಣಯವು ಕೋಡ್ನ ತುಣುಕನ್ನು ನಕಲಿಸಿರುವ ಸಂದರ್ಭಗಳನ್ನು ಗುರುತಿಸುತ್ತದೆ ಮತ್ತು ಅದರಲ್ಲಿ ಕೆಲವು ಹೆಸರುಗಳನ್ನು ಬದಲಾಯಿಸಲು ಪ್ರಾರಂಭಿಸಲಾಗಿದೆ, ಆದರೆ ಒಂದು ಸ್ಥಳದಲ್ಲಿ ಅವರು ಅದನ್ನು ಸರಿಪಡಿಸಿಲ್ಲ.
ಎರಡನೇ ಬ್ಲಾಕ್ನಲ್ಲಿ ಅವರು ಬದಲಾಗಿದ್ದಾರೆ ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಗಮನಿಸಿ ಆಪ್ 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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ವರ್ಗದ ಸದಸ್ಯರಂತೆಯೇ ಫಂಕ್ಷನ್ ಆರ್ಗ್ಯುಮೆಂಟ್ಗಳನ್ನು ನೀಡುವುದು ತುಂಬಾ ಅಪಾಯಕಾರಿ. ಗೊಂದಲಕ್ಕೀಡಾಗುವುದು ತುಂಬಾ ಸುಲಭ. ಅಂತಹ ಒಂದು ಪ್ರಕರಣ ನಮ್ಮ ಮುಂದಿದೆ. ಈ ಅಭಿವ್ಯಕ್ತಿ ಅರ್ಥವಿಲ್ಲ:
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: ಅವರು ಸೂಚ್ಯಂಕವನ್ನು ಪರಿಶೀಲಿಸಲು ಮರೆತಿದ್ದಾರೆ
ಹಿಂದೆ, ನಾವು ರೋಗನಿರ್ಣಯದ ಪ್ರಚೋದನೆಯ ಉದಾಹರಣೆಗಳನ್ನು ನೋಡಿದ್ದೇವೆ
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-ಸ್ಟುಡಿಯೋ ಎಚ್ಚರಿಕೆ:
ನಂತಹ ಕಂಟೇನರ್ನ ಅಂತ್ಯಕ್ಕೆ ಒಂದು ಅಂಶವನ್ನು ಸೇರಿಸಲು ಎಸ್ಟಿಡಿ:: ವೆಕ್ಟರ್ > ನೀವು ಕೇವಲ ಬರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ 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-ಸ್ಟುಡಿಯೋ ಸಾಮಾನ್ಯ ಸನ್ನಿವೇಶವಲ್ಲ.
ನಿಮ್ಮ ಕೋಡ್ನ ಗುಣಮಟ್ಟ ಮತ್ತು ವಿಶ್ವಾಸಾರ್ಹತೆಯನ್ನು ಸುಧಾರಿಸುವಲ್ಲಿ ಅದೃಷ್ಟ!
ನೀವು ಈ ಲೇಖನವನ್ನು ಇಂಗ್ಲಿಷ್ ಮಾತನಾಡುವ ಪ್ರೇಕ್ಷಕರೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಲು ಬಯಸಿದರೆ, ದಯವಿಟ್ಟು ಅನುವಾದ ಲಿಂಕ್ ಬಳಸಿ: ಆಂಡ್ರೆ ಕಾರ್ಪೋವ್.
ಮೂಲ: www.habr.com