
KDE(K Desktop Environmentの略)は、主にLinuxおよびその他のUNIXライクシステム用のデスクトップ環境です。 簡単に言えば、これがすべてのグラフィックデザインの責任です。 この環境は、クロスプラットフォームのQtユーザーインターフェイス開発ツールに基づいて構築されています。 フリーソフトウェアのアイデアに専念している世界中の数百人のプログラマーが開発に従事しています。 KDEは、最新のグラフィカルインターフェイスでオペレーティングシステムと対話できるユーザー環境アプリケーションの完全なセットを提供します。 KDEの内部を見てみましょう。
KDEプロジェクトバージョン4.14の以下のパッケージ
は、 OpenSUSE Factoryで
PVS-Studio 5.19を使用してテストされました。
- KDE PIMライブラリ
- KDEベースライブラリ
- KDEベースアプリ
- KDE開発
KDE PIMライブラリ
V547式は常に真です。 ここでは、おそらく「&&」演算子を使用する必要があります。 occurrenceformatter.cpp 2684
enum PartStat { .... Accepted, Tentative, .... }; static QString formatICalInvitationHelper(....) { .... a = findDelegatedFromMyAttendee( inc ); if ( a ) { if ( a->status() != Attendee::Accepted ||
式は常に真です。 理由は、タイプミスまたはプログラマロジックの誤りです。 おそらく、ここで「&&」演算子を使用する必要があります。
同様の不審な場所:
- V547式は常に真です。 ここでは、おそらく「&&」演算子を使用する必要があります。 occurrenceformatter.cpp 3293
V593 「A = B == C」という表現を検討することを検討してください。 式は、「A =(B == C)」のように計算されます。 kio_ldap.cpp 535
void LDAPProtocol::del( const KUrl &_url, bool ) { .... if ( (id = mOp.del( usrc.dn() ) == -1) ) { LDAPErr(); return; } ret = mOp.waitForResult( id, -1 ); .... }
比較演算子(==)の優先順位は、割り当て演算子(=)の優先順位よりも高くなっています。 運のおかげで、条件は計画どおりに満たされますが、0に等しいid idの誤った値が使用されます。
V595 nullptrに対して検証される前に、「incBase」ポインターが使用されました。 行をチェック:2487、2491。occurrenceformatter.cpp 2487
static QString formatICalInvitationHelper(....) { .... incBase->shiftTimes( mCalendar->timeSpec(), ....); Incidence *existingIncidence = 0; if ( incBase && helper->calendar() ) { .... } .... }
'incBase'ポインターの逆参照は、チェックする前に行われます。
V622 「switch」ステートメントの検査を検討してください。 最初の「ケース」演算子が欠落している可能性があります。 listjob.cpp 131
void ListJob::doStart() { Q_D( ListJob ); switch ( d->option ) { break;
ステートメントブロック「switch」では、最初のステートメントは「case」ではありません。 これは、コードフラグメントが制御を取得しないという事実につながります。 最良の場合、「break」ステートメントは古い条件が完全に削除された後も残りますが、最悪の場合、ここでは別の「case」が省略されます。
V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「lexBuf.strs」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 vcc.y 638
static void lexAppendc(int c) { lexBuf.strs = (char *) realloc(lexBuf.strs, (size_t) .... + 1); lexBuf.strs[lexBuf.strsLen] = c; .... }
この式は潜在的に危険です。realloc関数の結果を別の変数に格納することをお勧めします。 realloc()関数は、メモリブロックのサイズを変更します。 エラーが発生した場合、古いメモリ領域へのポインタは失われます。
とにかく、そのようなコードは悪いです。 realloc()関数が返したものの検証はありません。 ポインタは次の行ですぐに逆参照されます。
同様の場所:
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「mods」は失われます。 realloc()を一時ポインターに割り当てることを検討してください。 ldapoperation.cpp 534
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインター 'mods [i]-> mod_vals.modv_bvals'が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 ldapoperation.cpp 579
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインター 'ctrls'が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 ldapoperation.cpp 624
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「fp-> s」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 vobject.c 1055
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「lexBuf.strs」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 vcc.y 635
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「lexBuf.strs」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 vcc.y 643
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「バイト」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 vcc.y 928
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「fp-> s」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 vobject.c 1050
KDEベースライブラリ
V523 「then」ステートメントは「else」ステートメントと同等です。 kconfig_compiler.cpp 1051
QString newItem( const QString &type, ....) { QString t = "new "+cfg.inherits+"::Item" + ....; if ( type == "Enum" ) t += ", values" + name; if ( !defaultValue.isEmpty() ) { t += ", "; if ( type == "String" ) t += defaultValue;
ifステートメントの同じtrueおよびfalseブランチは非常に疑わしく見えます。 コードに誤字が含まれていない場合は、たとえば次のように簡略化できます。
if ( !defaultValue.isEmpty() ) t += ", " + defaultValue;
同様の場所:
- V523「then」ステートメントは「else」ステートメントと同等です。 installation.cpp 589
V595 nullptrに対して検証される前に、「
priv- >スライダー」ポインターが使用されました。 行をチェック:786、792。knuminput.cpp 786
void KDoubleNumInput::spinBoxChanged(double val) { .... const double slidemin = priv->slider->minimum();
「priv」ポインターの逆参照は、チェックする前に行われます。
同様の危険スポット:
- V595 nullptrに対して検証される前に、「m_instance」ポインターが使用されました。 行を確認してください:364、376。ksystemtimezone.cpp 364
- V595 nullptrに対して検証される前に、「ジョブ」ポインターが使用されました。 行を確認してください:778、783。knewfilemenu.cpp 778
V646アプリケーションのロジックの検査を検討してください。 「else」キーワードが欠落している可能性があります。 karchive.cpp 187
*bool KArchive::close() { ....
このコードスニペットは、「else」キーワードが欠落していること、または非常に見苦しくて混乱を招くコード設計であることを示している場合があります。
V655ストリングは連結されましたが、使用されません。 式を調べることを検討してください。 entrydetailsdialog.cpp 225
void EntryDetails::updateButtons() { .... foreach (....) { QString text = info.name; if (!info.distributionType.trimmed().isEmpty()) { text + " (" + info.distributionType.trimmed() + ")";
アナライザーは、未使用のストリング変数共用体を検出しました。 おそらく、コードは次のようになります。
text += " (" + info.distributionType.trimmed() + ")";
同様の場所:
- V655ストリングは連結されましたが、使用されません。 式を調べることを検討してください。 itemsgridviewdelegate.cpp 365
- V655ストリングは連結されましたが、使用されません。 式を調べることを検討してください。 itemsviewdelegate.cpp 159
V705 「else」ブロックが忘れられているかコメントアウトされている可能性があり、そのためプログラムの動作ロジックが変更されています。 entrydetailsdialog.cpp 149
void EntryDetails::entryChanged(const KNS3::EntryInternal& entry) { .... if(m_entry.previewUrl(EntryInternal::PreviewSmall1).isEmpty()){ ui->previewBig->setVisible(false); } else
このコードフラグメントの設計もあいまいに見えます。 「else if」コンストラクトはここで計画されましたか、または「else if」の削除を忘れましたか?
V612ループ内の無条件の「戻り」。 bufferfragment_p.h 94
BufferFragment split(char c, unsigned int* start) { while (*start < len) { int end = indexOf(c, *start); if (end == -1) end = len; BufferFragment line(d + (*start), end - (*start)); *start = end + 1; return line; } return BufferFragment(); }
1回の繰り返しのためにループを書く価値がありましたか? それとも、条件付きステートメントがないのですか?
V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「d」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 netwm.cpp 596
template <class Z> void NETRArray<Z>::reset() { sz = 0; capacity = 2; d = (Z*) realloc(d, sizeof(Z)*capacity); memset( (void*) d, 0, sizeof(Z)*capacity ); }
KDE PIMライブラリのように、メモリを拡張できない場合、古いメモリ領域へのポインタが失われる可能性があるため、realloc()関数で単一のポインタを使用することは推奨されません。
同様の場所:
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「ハンドラ」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 kxerrorhandler.cpp 94
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「バッファ」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 netwm.cpp 528
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「d」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 netwm.cpp 608
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「ptr」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 kdesu_stub.c 119
- V701 realloc()リークの可能性:realloc()がメモリの割り当てに失敗すると、元のポインタ「addr.generic」が失われます。 realloc()を一時ポインターに割り当てることを検討してください。 k3socketaddress.cpp 372
KDEベースアプリ
V501 「&&」演算子の左と右に同じサブ式「mimeData-> hasFormat(QLatin1String( "application / x-kde-ark-dndextract-service"))」があります。 iconview.cpp 2357
void IconView::dropEvent(QGraphicsSceneDragDropEvent *event) { .... if (mimeData->hasFormat(QLatin1String( "application/x-kde-ark-dndextract-service")) &&
アナライザーは同じ条件式を検出しました。 条件演算子の本体では、条件が次のようになっていると仮定するのが論理的です。
if (mimeData->hasFormat(QLatin1String( "application/x-kde-ark-dndextract-service")) &&
V595 nullptrに対して検証される前に、「m_view」ポインターが使用されました。 行を確認してください:797、801。kitemlistcontroller.cpp 797
bool KItemListController::mouseDoubleClickEvent(....) { const QPointF pos = transform.map(event->pos()); const int index = m_view->itemAt(pos);
KDEプロジェクトでは、関数に入ってきたポインターが最初にローカル変数を初期化するために使用され、後で参照解除される前にチェックされる多くの場所がありました。
V637反対の2つの条件が発生しました。 2番目の条件は常にfalseです。 チェック行:410、412。kebsearchline.cpp 410
void KViewSearchLine::slotColumnsRemoved(const QModelIndex &, int first, int last) { if(d->treeView) updateSearch(); else { if(d->listView->modelColumn() >= first && d->listView->modelColumn() <= last) { if(d->listView->modelColumn()>last)
ネストされた条件は常にfalseです。 この条件は、いくつかの編集まで関連していたと想定できます。
V654ループの条件 'state!= 1'は常に真です。 passwd.cpp 255
int PasswdProcess::ConversePasswd(....) { .... state = 0; while (state != 1) { line = readLine(); if (line.isNull()) {
変数 'state'の値はループ内で変化しないため、停止条件は 'return'の呼び出しのみです。
KDE開発
V501 「&&」演算子の左側と右側には、同一のサブ式「file == rhs.file」があります。 pp-macro.cpp 44
bool pp_macro::operator==(const pp_macro& rhs) const { if(completeHash() != rhs.completeHash()) return false; return name == rhs.name && file == rhs.file &&
アナライザーは、条件式が繰り返される複数の場所を検出しました。 これのいくつかは深刻なタイプミスかもしれません。
このような他の場所:
- V501「||」の左側と右側に同一の副次式「tokenKind == Token_not_eq」があります。 演算子。 builtinoperators.cpp 174
- V501「||」の左右に同一の副次式「!Context-> owner()」があります。 演算子。 typeutils.cpp 194
V595 nullparentに対して検証される前に、「parentJob()-> cpp()」ポインターが使用されました。 行を確認してください:437、438。cppparsejob.cpp 437
void CPPInternalParseJob::run() { .... QReadLocker lock(parentJob()->parentPreprocessor() ? 0: parentJob()->cpp()->language()->parseLock());
そして、このプロジェクトには、チェックする前にポインターを間接参照する場所がありました。
別の場所:
- V595 nullparentに対して検証される前に、「parentContext()」ポインターが使用されました。 行をチェック:692、695。context.cpp 692
V564 「&」演算子はブール型の値に適用されます。 括弧を含めるのを忘れているか、「&&」演算子を使用することを意図している可能性があります。 usedecoratorvisitor.cpp 40
DataAccess::DataAccessFlags typeToDataAccessFlags(....) { DataAccess::DataAccessFlags ret = DataAccess::Read; TypePtr< ReferenceType > reftype=type.cast<ReferenceType>(); if(reftype && reftype->baseType() && !reftype->baseType()->modifiers() &
著者は、エラーがここにあるかどうかをよく知っていますが、「&」演算子は疑わしいように見えます。 式 "!Reftype-> baseType()-> modifiers()"は、タイプが 'bool'であることに注意してください。
V555式「m_pos-backOffset> 0」は「m_pos!= BackOffset」として機能します。 pp-stream.cpp 225
unsigned int rpp::Stream::peekLastOutput(uint backOffset) const { if(m_pos - backOffset > 0) return m_string->at(m_pos - backOffset - 1); return 0; }
負の結果は非常に大きな正の数として解釈される可能性があるため、符号なしの数の差をゼロと比較することは完全に正しいとは限りません。 条件本体に巨大なインデックスを取得しないようにするには、次のように条件を記述することをお勧めします。
if(m_pos > backOffset) return m_string->at(m_pos - backOffset - 1);
同様の場所:
- V555式「nextOffset-currentOffset> 0」は、「nextOffset!= CurrentOffset」として機能します。 pp-location.cpp 211
おわりに
KDE製品のユーザーと開発者の大勢の聴衆はテストの面で大きな役割を果たしますが、さまざまなコードアナライザーに注意を払う価値もあります。 ただし、インターネット上の出版物から判断すると、少なくともCoverityはすでにKDEソースコードをチェックするために使用されています。 これが原因で、PVS-Studioが疑わしい場所をほとんど見つけることができません。
静的分析を定期的に使用することで、より便利なタスクを解決するために多くの時間を節約できます。 また、コードの品質管理は、たとえば、新しいサービスを使用して
、C / C ++コードの定期的な監査など、他のサービスに移行でき
ます 。
この記事は英語です。
英語を話す聴衆とこの記事を共有したい場合は、翻訳へのリンクを使用してください:Svyatoslav Razmyslov。
KDEに興味を持つユニコーン 。