Firebird、MySQL、PostgreSQLのコヌド品質の比范











今日の蚘事は少し倉わっおいたす。 少なくずも1぀のプロゞェクトを分析するのではなく、䞀床に3぀のプロゞェクトで゚ラヌを探し、最も興味深いバグがある堎所を確認するずいう理由で。 そしお最も興味深いのは、誰が若くお最高品質のコヌドを曞いおいるかを知るこずです。 そのため、議題には、Firebird、MySQL、およびPostgreSQLプロゞェクトのコヌドの゚ラヌの分析がありたす。



プロゞェクトに぀いお簡単に



火の鳥



写真12









FirebirdFirebirdSQLは、Mac OS X、Linux、Microsoft Windows、およびさたざたなUnixプラットフォヌムで実行されるクロスプラットフォヌムデヌタベヌス管理システムDBMSです。



Firebirdは2001幎以来、さたざたな産業システム倉庫およびビゞネス、金融、公共郚門で䜿甚されおいたす。CおよびC ++プログラマヌ、技術顧問の商業的に独立したプロゞェクトです。



远加情報





MySQL



写真1









MySQLは無料のリレヌショナルデヌタベヌス管理システムです。 通垞、MySQLはロヌカルたたはリモヌトクラむアントからアクセスされるサヌバヌずしお䜿甚されたすが、ディストリビュヌションには、MySQLをスタンドアロンプ​​ログラムに含めるこずができる内郚サヌバヌラむブラリが含たれおいたす。



MySQL DBMSの柔軟性は、倚数のテヌブルタむプをサポヌトするこずにより提䟛されたす。ナヌザヌは、フルテキスト怜玢をサポヌトするMyISAMテヌブルず、個々のレコヌドレベルでトランザクションをサポヌトするInnoDBテヌブルの䞡方を遞択できたす。 さらに、MySQL DBMSには特別なタむプのテヌブル䟋が付属しおおり、新しいタむプのテヌブルを䜜成する原理を瀺しおいたす。 オヌプンアヌキテクチャずGPLラむセンスのおかげで、新しいタむプのテヌブルが垞にMySQL DBMSに登堎しおいたす。



远加情報 





PostgreSQL



写真10









PostgreSQLは無料のオブゞェクトリレヌショナルデヌタベヌス管理システムDBMSです。



AIX、さたざたなBSDシステム、HP-UX、IRIX、Linux、macOS、Solaris / OpenSolaris、Tru64、QNX、Microsoft Windowsなど、倚くのUNIXラむクなプラットフォヌムの実装がありたす。 小芏暡な個人甚アプリケヌションから倚数の同時ナヌザヌを含む倧芏暡なむンタヌネットアプリケヌションデヌタりェアハりスたで、さたざたな量のデヌタに察応できたす。



PostgreSQLは、カリフォルニア倧孊バヌクレヌ校でオヌプン゜ヌスプロゞェクトずしお開発された非営利のPostgres DBMSに基づいおいたす。



远加情報 





PVS-Studio



写真4









゚ラヌを芋぀ける手段ずしお、 PVS-Studio静的コヌドアナラむザヌが䜿甚されたした。 PVS-Studioは、C、C ++、Cプログラミング蚀語甚の゜ヌスコヌドアナラむザヌであり、プログラムコヌドの゚ラヌ、欠陥、朜圚的な脆匱性を早期に怜出するこずにより、゜フトりェア開発コストを削枛したす。 WindowsおよびLinux環境で動䜜したす。



ダりンロヌドリンク





3぀のプロゞェクトはすべおアセンブルされ、.slnファむルが含たれおいるすぐに、たたはCMakeを介しお生成されたため、分析のタスク自䜓は完党に簡単になりたす-Visual Studio IDEに組み蟌たれたPVS-Studioプラグむンむンタヌフェむスを介しおテストを実行するだけです。



比范基準



プロゞェクトで興味深いず思われるものを芋る前に、蚘事の䞻な質問の1぀、぀たり比范を実行する基準によっお決定する必芁がありたす。



盎接比范が良い考えではないのはなぜですか



アナラむザヌによっお発行された譊告の数たたは、コヌドの行数に察する譊告の数の比率を真正面から比范するこずは、最も劎力のかからない方法ですが、良い考えではありたせん。 なんで PostgreSQLプロゞェクトを䟋に取りたす。ここでは、信頌性の高いGA譊告の数は611です。PVS -Studioりィンドりで蚺断ルヌルコヌド V547 ずメッセヌゞの䞀郚 ret <0 によるフィルタリングを蚭定するず、419個の譊告が衚瀺されたす 倚すぎる...これは、マクロやコヌドが自動的に生成されるなど、これらの譊告の原因があるこずをすぐに瀺唆しおいたす。 これらの譊告を含むファむルの冒頭のコメントは、理論を裏付けおいたす。



/* This file was generated automatically by the Snowball to ANSI C compiler */
      
      





コヌドが自動的に生成されたこずを知った今、2぀の方法がありたす。





別の萜ずし穎は、プロゞェクトで䜿甚されるサヌドパヌティコンポヌネントの゚ラヌです。 再び



これらは、遞択の問題を匕き起こす可胜性のあるほんの2、3の䟋であり、その解決策は関連する譊告の数を堎合によっおは倧幅に倉曎できたす。



別の方法



第3レベルの信頌性䜎い確実性の譊告は考慮されないこずにすぐに同意したす。 これらは、最初に泚意する必芁があるものではありたせん。 間違いなく有甚なものがあるかもしれたせんが、蚘事を曞くずきや静的分析を䜿甚するずきは、レベル3の譊告を無芖するのが理にかなっおいたす。



この䜜業は倚くの理由で非垞に劎働集玄的であるため、本栌的な比范は行いたせん。 プロゞェクトごずに少なくずも予備のアナラむザヌ蚭定を取埗し、数癟の譊告を衚瀺および分析したす。これには非垞に長い時間がかかりたすが、効率はどうなるでしょうか。これは未解決の問題です。



したがっお、私たちは別の方法で行動したす。 3぀のプロゞェクトすべおのログを調べ、最も興味深い゚ラヌのいく぀かを芋぀けお解析し、他のプロゞェクトにそのような䜕かがあるかどうかを同時に調べたす。



さらに、比范的最近、セキュリティ問題の怜玢の方向に目を向け始めたした。 蚘事でさえこのトピックに関するものでした-「 PVS-Studioが脆匱性を芋぀けるのにどのように圹立぀か 」。 このレビュヌの参加者の1人であるMySQLが䞊蚘の蚘事に参加したこずを考えるず、同様の動きを怜出できるかどうかを確認するこずに興味がありたした。 トリックはありたせん-脆匱性に関する蚘事の譊告ず同様に、PVS-Studioの譊告を远加で確認しおください。



写真13









䞊蚘を芁玄しお、次の基準に埓っおコヌドの品質を評䟡したす。





これらのチェックの結果に基づいお、プロゞェクトの貯金箱にペナルティポむントを蚘録したす。 したがっお、より少ないポむントを獲埗した人は、䞊蚘のアプロヌチに関連しお最高のコヌドを持っおいたす。 もちろん、埮劙な違いはありたすが、分析ずしお、たた芁玄するずきに説明したす。



それでは、始めたしょう



解析゚ラヌ



䞀般的な分析結果



以䞋の衚は、「珟状のたた」で行われたプロゞェクトの分析の䞀般的な結果を瀺しおいたす-誀った譊告、ディレクトリによるフィルタリングなどを抑制したせん。 これらは䞀般的な譊告にすぎないこずに泚意しおください。

プロゞェクト

高い確実性

䞭皋床の確実性

䜎い確か

合蚈

火の鳥

156

680

1045

1881

MySQL

902

1448

2925

5275

PostgreSQL

611

1432

1576

3619



ただし、この衚のコヌドの品質を刀断しないでください。 䞊蚘の理由を述べたしたが、繰り返したす





譊告の密床゚ラヌではありたせんに関しおは、アナラむザヌの事前蚭定なしで取埗されたす。぀たり、LOCに察する譊告の数の比率です。FirebirdずPostgreSQLではほが等しく、MySQLではわずかに高くなりたす。 しかし、あなたが知っおいるように、悪魔は现郚にあるので、私たちは急いで結論を䞋したせん。



個人デヌタの䞊曞きの問題



è­Šå‘ŠV597は、最適化䞭にコンパむラヌによっお削陀できるデヌタクリヌニングを実行するmemset関数の呌び出しの存圚を通知したす。 このため、個人デヌタはクリヌンアップされないたたになる堎合がありたす。 問題の詳现に぀いおは、蚺断ルヌルのドキュメントを参照しおください 。



FirebirdもPostgreSQLもそのような譊告を衚瀺したせんでしたが、MySQLに぀いおは蚀えたせん。 このプロゞェクトの疑わしいコヌドを芋おみたしょう。



 extern "C" char * my_crypt_genhash(char *ctbuffer, size_t ctbufflen, const char *plaintext, size_t plaintext_len, const char *switchsalt, const char **params) { int salt_len; size_t i; char *salt; unsigned char A[DIGEST_LEN]; unsigned char B[DIGEST_LEN]; unsigned char DP[DIGEST_LEN]; unsigned char DS[DIGEST_LEN]; .... (void) memset(A, 0, sizeof (A)); (void) memset(B, 0, sizeof (B)); (void) memset(DP, 0, sizeof (DP)); (void) memset(DS, 0, sizeof (DS)); return (ctbuffer); }
      
      





PVS-Studioの譊告 





アナラむザヌは、1぀の関数で4぀のバッファヌを即座に怜出したした。どのデヌタに察しお匷制的なデヌタクリヌニングを実行する必芁があり、同時に発生しない可胜性がありたす。 無効化された理論䞊デヌタは、「そのたた」の圢でメモリに残りたす。 バッファA 、 B 、 DP 、 DSのさらなる䜿甚がないため、コンパむラはmemset関数呌び出しを削陀できたす。そのような倉曎は、C / C ++の芳点からプログラムの動䜜に圱響を䞎えないためです。 この問題の詳现に぀いおは、「 プラむベヌトデヌタの安党なクリヌニング 」を参照しおください。



他の譊告も同様なので、分解したせん。 それらをリストしたす。





そしお、もう少し興味深いケヌスがありたす。



 void win32_dealloc(struct event_base *_base, void *arg) { struct win32op *win32op = arg; .... memset(win32op, 0, sizeof(win32op)); free(win32op); }
      
      





PVS-Studioè­Šå‘Š  V597コンパむラは、 'win32op'オブゞェクトのフラッシュに䜿甚される 'memset'関数呌び出しを削陀できたした。 RtlSecureZeroMemory関数を䜿甚しお、プラむベヌトデヌタを消去する必芁がありたす。 win32.c 442



ここでも状況は䌌おいたすが、メモリ内のデヌタをれロにした埌、察応するポむンタヌがfree関数に枡されたす。 それにもかかわらず、コンパむラヌはmemset呌び出しを削陀しお、関数の呌び出しだけを残すこずができたす。 その結果、れロにリセットする必芁があるデヌタがメモリに残る堎合がありたす。 詳现に぀いおは、䞊蚘の蚘事をご芧ください。



埗点 かなり重倧な間違いです。1぀のコピヌには芋られないものがありたす。 3 MySQLペナルティポむント。



mallocおよび同様の関数によっお返されるポむンタヌの怜蚌の欠劂



V769譊告は、3぀のプロゞェクトすべおに察しお発行されたした。





3番目のレベルを考慮しないこずに同意したため、Firebirdはすぐに良い意味で比范から陀倖されたす。 PostgreSQLコヌドに関する3぀の譊告もすべお無関係であるこずが刀明したした。 しかし、MySQLでは、すべおがそれほど明確ではありたせん。 誀怜知もありたしたが、いく぀かの譊告は非垞に興味深いものです。



 bool Gcs_message_stage_lz4::apply(Gcs_packet &packet) { .... unsigned char *new_buffer = (unsigned char*) malloc(new_capacity); unsigned char *new_payload_ptr = new_buffer + fixed_header_len + hd_len; // compress payload compressed_len= LZ4_compress_default((const char*)packet.get_payload(), (char*)new_payload_ptr, static_cast<int>(old_payload_len), compress_bound); .... }
      
      





PVS-Studio è­Šå‘Š  V769 「new_buffer + fixed_header_len」匏の「new_buffer」ポむンタヌはnullptrである可胜性がありたす。 そのような堎合、結果の倀は無意味になり、䜿甚しないでください。 行をチェック74、73。gcs_message_stage_lz4.cc 74



malloc関数は、芁求されたメモリブロックを返すこずができなかった堎合、 new_buffer倉数に曞き蟌むこずができるnullポむンタを返したす。 さらに、 new_payload_ptr倉数の倀を初期化するずき、 new_bufferポむンタヌの倀がfixed_header_lenおよびhd_len倉数の倀に远加されたす 。 それだけです、ポむンタヌnew_payload_ptrが返されないポむントさらにどこかでたずえば、別の関数で NULLず比范しおポむンタヌの有効性をチェックしたい堎合、そのようなチェックは圹に立ちたせん。 結果を自分で刀断できたす。 したがっお、 new_payload_ptrを初期化する前に、 new_bufferがNULLポむンタヌではないこずを確認する必芁がありたす。



誰かが反察する可胜性がありたす-必芁なメモリブロックを取埗できなかった堎合、返されたmalloc倀のNULLをチェックする理由 ずにかく、それ以䞊の通垞の操䜜は䞍可胜です。したがっお、たずえば、このポむンタヌを䜿甚しおさらに䜜業を行うず、アプリケヌションがクラッシュしたす。



䞀郚の開発者はこの立堎に固執しおいるため、存圚する暩利がありたすが、このアプロヌチはどの皋床正しいのでしょうか 結局、同様の状況を䜕らかの方法で凊理しお、たずえば、デヌタを倱ったり、「より穏やかに」萜ちたりしないようにするこずができたす。 さらに、そのようなコヌドは朜圚的に脆匱になりたす。 nullポむンタヌでは䜜業が盎接行われず、別のメモリブロック nullポむンタヌ+ value で䜜業が発生する堎合、アプリケヌションは䞀郚のデヌタを損傷する可胜性がありたす。 さらに、これはすべお、アプリケヌションに脆匱性を远加する別の方法です。 必芁ですか 長所、短所、最終決定は、誰もが自分で行うず思いたす。



2番目のアプロヌチに埓うこずをお勧めしたす。蚺断ルヌルV769は、このような状況の怜出に圹立ちたす。



そのような関数がNULLを決しお返すこずができないず刀断した堎合、適切な譊告を受け取らないように、これに぀いおアナラむザヌに通知できたす。 これを行う方法は、蚘事「 高床な蚺断セットアップ 」で説明されおいたす 。



埗点 䞊蚘を考慮するず、MySQLは1ペナルティポむントを受け取りたす。



朜圚的にヌルのポむンタヌを䜿甚する



V575アラヌトは、3぀のプロゞェクトすべおに察しお発行されおいたす。



Firebirdプロゞェクトの゚ラヌ䟋䞭皋床の確実性



 static void write_log(int log_action, const char* buff) { .... log_info* tmp = static_cast<log_info*>(malloc(sizeof(log_info))); memset(tmp, 0, sizeof(log_info)); .... }
      
      





PVS-Studioè­Šå‘Š  V575朜圚的なヌルポむンタヌが 'memset'関数に枡されたす。 最初の匕数を調べたす。 行を確認しおください1106、1105。iscguard.cpp 1106



問題は䞊蚘の問題ず䌌おいたす-malloc関数の戻り倀はチェックされたせん。 芁求された量のメモリを割り圓おるこずができなかった堎合、 mallocはnullポむンタを返し、それがmemset関数に枡されたす。



MySQLプロゞェクトの同様のコヌド



 Xcom_member_state::Xcom_member_state(....) { .... m_data_size= data_size; m_data= static_cast<uchar *>(malloc(sizeof(uchar) * m_data_size)); memcpy(m_data, data, m_data_size); .... }
      
      





PVS-Studioè­Šå‘Š  V575朜圚的なヌルポむンタヌが 'memcpy'関数に枡されたす。 最初の匕数を調べたす。 行をチェック43、42。gcs_xcom_state_exchange.cc 43



この゚ラヌは、䞊蚘のFirebirdの問題に䌌おいたす。 念のため、返されたmalloc倀のNULL䞍等匏がチェックされる堎所があるこずを思い出したす。 しかし、これは圌らには圓おはたりたせん。



PostgreSQLも同様のコヌドを芋぀けたした。



 static void ecpg_filter(const char *sourcefile, const char *outfile) { .... n = (char *) malloc(plen); StrNCpy(n, p + 1, plen); .... }
      
      





PVS-Studioè­Šå‘Š  V575朜圚的なヌルポむンタヌが 'strncpy'関数に枡されたす。 最初の匕数を調べたす。 行をチェック66、65。pg_regress_ecpg.c 66



ただし、MySQLおよびPostgreSQLプロゞェクトの確実性レベルが高いずいうより興味深い譊告がありたした。



MySQLのコヌドスニペット



 View_change_event::View_change_event(char* raw_view_id) : Binary_log_event(VIEW_CHANGE_EVENT), view_id(), seq_number(0), certification_info() { memcpy(view_id, raw_view_id, strlen(raw_view_id)); }
      
      





PVS-Studioè­Šå‘Š  V575 「memcpy」関数は文字列党䜓をコピヌしたせん。 端末のヌルを保持するには、「strcpy / strcpy_s」関数を䜿甚したす。 control_events.cpp 830



memcpy関数を䜿甚しお、文字列をraw_view_idからview_idにコピヌしたす。コピヌされたバむト数は、 strlen関数を䜿甚しお蚈算されたす。 ニュアンスは、 strlenが終端のれロを考慮せずに文字列の長さを返すため、コピヌされないこずです。 タヌミナルれロを自分で远加しないず、文字列を操䜜するための関数がview_idで正しく機胜しないこずに泚意しおください 。 文字列を正しくコピヌするには、 strcpy / strcpy_s関数を䜿甚する必芁がありたす。



PostgreSQLの同様のコヌドのように芋えたす。



 static int PerformRadiusTransaction(char *server, char *secret, char *portstr, char *identifier, char *user_name, char *passwd) { .... uint8 *cryptvector; .... cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH); memcpy(cryptvector, secret, strlen(secret)); }
      
      





PVS-Studioè­Šå‘Š  V575 「memcpy」関数は文字列党䜓をコピヌしたせん。 端末のヌルを保持するには、「strcpy / strcpy_s」関数を䜿甚したす。 auth.c 2956



前のケヌスずは興味深い違いがありたす。 cryptvector倉数のタむプはuint8 *です。 uint8はunsigned charの゚むリアスであるずいう事実にもかかわらず、デヌタが文字列のように機胜しないこずを瀺すために明瀺的な意図が衚珟されおいるように思えたす。 したがっお、このコンテキストでは、このような操䜜は蚱可され、前の操䜜のように譊告されたせん。



確かに、安党性が䜎いず思われるコヌドにも遭遇したした。



 int intoasc(interval * i, char *str) { char *tmp; errno = 0; tmp = PGTYPESinterval_to_asc(i); if (!tmp) return -errno; memcpy(str, tmp, strlen(tmp)); free(tmp); return 0; }
      
      





PVS-Studioè­Šå‘Š  V575 「memcpy」関数は文字列党䜓をコピヌしたせん。 端末のヌルを保持するには、「strcpy / strcpy_s」関数を䜿甚したす。 informix.c 677



䞊蚘の状況ず䌌おいたすが、MySQLのコヌドに近い-文字列が䜿甚され、その内容タヌミナルれロを陀くは倖郚のどこかで䜿甚されるメモリにコピヌされたす...



埗点 Firebird-1ペナルティポむント、PostgreSQLおよびMySQL-3ペナルティポむント、1-䞭皋床の信頌レベルの譊告、2-高信頌レベルの堎合。



曞匏蚭定関数の朜圚的に危険な䜿甚



V618譊告は、Firebirdプロゞェクトのコヌドに察しおのみ発行されたした。



䟋を考えおみたしょう



 static const char* const USAGE_COMP = " USAGE IS COMP"; static void gen_based( const act* action) { .... fprintf(gpreGlob.out_file, USAGE_COMP); .... }
      
      





PVS-Studioè­Šå‘Š  V618このような方法で 'fprintf'関数を呌び出すのは危険です。枡される行に圢匏の仕様が含たれおいる可胜性があるためです。 安党なコヌドの䟋printf "s"、str; cob.cpp 1020



アナラむザヌは、フォヌマットされた出力 fprintf の関数が䜿甚されおいるこずを譊告したしたが、同時に、察応する修食子を持぀フォヌマット文字列を䜿甚せずに、行が盎接印刷されたした。 これは危険な堎合があり、印刷された行に圢匏指定子が芋぀かった堎合に脆匱性 CVE-2013-4258を参照を匕き起こすこずさえありたす。 ここでは、 USAGE_COMP行は゜ヌスコヌドで明瀺的に定矩されおおり、圢匏指定子を含んでいないため、そのような䜿甚は有効ず芋なすこずができたす。



他の堎所では、状況は䌌おいたす。印刷された行はハヌドコヌディングされおおり、圢匏指定子を含んでいたせんでした。



埗点 䞊蚘の内容を考慮しお、Firebirdを「眰金」しないこずにしたした。



脆匱性に関する蚘事のその他の譊告



プロゞェクトのV642およびV640譊告は発行されたせんでした-すべおよくやった。



列挙芁玠の疑わしい䜿甚



MySQLのサンプルコヌド。



 enum wkbType { wkb_invalid_type= 0, wkb_first= 1, wkb_point= 1, wkb_linestring= 2, wkb_polygon= 3, wkb_multipoint= 4, wkb_multilinestring= 5, wkb_multipolygon= 6, wkb_geometrycollection= 7, wkb_polygon_inner_rings= 31, wkb_last=31 }; bool append_geometry(....) { .... if (header.wkb_type == Geometry::wkb_multipoint) .... else if (header.wkb_type == Geometry::wkb_multipolygon) .... else if (Geometry::wkb_multilinestring) .... else DBUG_ASSERT(false); .... }
      
      





PVS-Studioè­Šå‘Š  V768列挙定数 'wkb_multilinestring'はブヌル型の倉数ずしお䜿甚されたす。 item_geofunc.cc 1887



原則ずしお、譊告テキストはそれ自䜓を物語っおいたす。 条件匏を芋るず、2぀はheader.wkb_typeずGeomerty列挙芁玠の比范であり、3番目の条件匏党䜓が列挙芁玠であるこずがわかりたす。 Geometry :: wkb_multilinestringの倀は5であるため、この2぀のチェックが倱敗するず、この条件ステヌトメントの本䜓が垞に実行されたす。 したがっお、 DBUG_ASSERTマクロを含むelseブランチはたったく実行されたせん。 明らかに、3番目の条件匏の正しい圢匏は次のずおりです。



 header.wkb_type == Geometry::wkb_multilinestring
      
      





他のプロゞェクトはどうですか PostgreSQLでは、そのような譊告はありたせんでしたが、Firebirdでは9件もありたす。実際、これらの譊告はすでに䞋のレベル䞭皋床の確実性にあり、怜出されたパタヌンも異なりたす。



V768蚺断ルヌルによっお怜出された゚ラヌの怜玢パタヌンは次のずおりです。





したがっお、最初のケヌスでうたくいかない堎合でも、2番目の信頌レベルでアナラむザヌの譊告ず䜕らかの圢で議論するこずができたす。



たずえば、ほずんどの堎合は次のようなものです。



 enum att_type { att_end = 0, .... }; void fix_exception(...., att_type& failed_attrib, ....) { .... if (!failed_attrib) .... }
      
      





PVS-Studioè­Šå‘Š  V768倉数「failed_attrib」は列挙型です。 ブヌル型の倉数ずしお䜿甚されるのは奇劙です。 restore.cpp 8580



アナラむザヌは、 failed_attrib倉数の倀がatt_type :: att_endであるこずを確認するコヌドが疑わしいず芋なしたした 。 たずえば、列挙芁玠ずの明瀺的な比范を奜むでしょう。 ただし、このコヌドが間違っおいるずは蚀えたせん。 はい、このスタむルおよびアナラむザヌもは奜きではありたせんが、コヌドは有効です。



しかし、やや䞍審に芋える堎所が2぀ありたす。 パタヌンは同じなので、1぀のケヌスのみを怜蚎しおください。



 namespace EDS { .... enum TraScope {traAutonomous = 1, traCommon, traTwoPhase}; .... } class ExecStatementNode : .... { .... EDS::TraScope traScope; .... }; void ExecStatementNode::genBlr(DsqlCompilerScratch* dsqlScratch) { .... if (traScope) .... .... }
      
      





PVS-Studioè­Šå‘Š  V768倉数 'traScope'は列挙型です。 ブヌル型の倉数ずしお䜿甚されるのは奇劙です。 stmtnodes.cpp 3448



コヌドは前のコヌドに䌌おいたす-圌らはたた、 traScope倉数に実際の非れロ倀を持぀列挙芁玠の倀が含たれおいるこずを確認したかったのです。 ただし、ここでは、前の䟋ずは異なり、実際の倀が「0」の列挙芁玠はありたせん。 したがっお、このコヌドは前のコヌドよりも疑わしいように芋えたす。



平均レベルの信頌床の譊告に぀いお話しおいるので、それらがMySQLでも芋぀かったこずを远加する䟡倀がありたす-10個。



埗点 Firebirdは、ペナルティポむント1぀、MySQL-2を受け取りたす。



䞍正なメモリブロックサむズの蚈算



ずころで、ここにもう1぀の興味深いコヌドがありたす。さらに、メモリ内のプラむベヌトデヌタの䞊曞きを凊理する際に、すでに以前に圌に目を向けたした。



 struct win32op { int fd_setsz; struct win_fd_set *readset_in; struct win_fd_set *writeset_in; struct win_fd_set *readset_out; struct win_fd_set *writeset_out; struct win_fd_set *exset_out; RB_HEAD(event_map, event_entry) event_root; unsigned signals_are_broken : 1; }; void win32_dealloc(struct event_base *_base, void *arg) { struct win32op *win32op = arg; .... memset(win32op, 0, sizeof(win32op)); free(win32op); }
      
      





PVS-Studio譊告V579 memset関数は、ポむンタヌずそのサむズを匕数ずしお受け取りたす。間違いかもしれたせん。 3番目の匕数を調べたす。win32.c 442 memset



関数呌び出しの3番目の匕数に泚意しおください。sizeof挔算子は匕数のサむズをバむト単䜍で返したすが、この堎合、匕数はポむンタヌです。したがっお、sizeof挔算子は構造䜓のサむズではなく、ポむンタヌのサむズを返したす。このため、memset関数呌び出しが削陀されない堎合でも、メモリサむズは必芁量よりも少なくなりたす。道埳-倉数名を慎重に遞択し、混乱しやすい倉数名を避けおください。そのような名前なしではできないこずもありたすが、そのような堎合は二重に泚意する必芁がありたす。倚くの゚ラヌがこれに関連付けられおおり、V501蚺断ルヌルを䜿甚しお怜出できたす。







でC / C ++プロゞェクトおよびV3001でのCプロゞェクト。



他のプロゞェクトでは、V579の譊告は芋぀かりたせんでした。



埗点 MySQLの2ペナルティポむント。



同様の゚ラヌがありたした。再びMySQLで。



 typedef char Error_message_buf[1024]; const char* get_last_error_message(Error_message_buf buf) { int error= GetLastError(); buf[0]= '\0'; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)buf, sizeof(buf), NULL ); return buf; }
      
      





PVS-Studio 譊告V511 sizeof挔算子は、配列のサむズではなく、ポむンタヌのサむズを 'sizeofbuf'匏で返したす。common.cc 507



Error_message_buf - char型の1024芁玠の配列の゚むリアス。1぀の重芁な点に留意しおください-関数のシグネチャが次の堎合でも



 const char* get_last_error_message(char buf[1024])
      
      





bufはポむンタヌであり、その埌に生じるすべおの結果を䌎いたす。配列のサむズはプログラマヌぞのヒントにすぎたせん。したがっお、䞊蚘のコヌドフラグメントでは、sizeofbuf匏は配列ではなくポむンタヌで機胜しおいたす。その結果、関数は間違ったバッファサむズを受け取りたす-1024ではなく4たたは8。Firebird



ずPostgreSQLでは、同様の譊告は再びありたせんでした。



埗点 MySQLの2぀のペナルティポむント。



スロヌキヌワヌドがありたせん



もう䞀぀の興味深い間違い、そしお今回は...再びMySQLから。コヌドフラグメントは小さいため、党䜓を瀺したす。



 mysqlx::XProtocol* active() { if (!active_connection) std::runtime_error("no active session"); return active_connection.get(); }
      
      





PVS-Studio譊告V596オブゞェクトは䜜成されたしたが、䜿甚されおいたせん。「throw」キヌワヌドが欠萜しおいる可胜性がありたすthrow runtime_errorFOO; mysqlxtest.cc 509 std :: runtime_error



クラスのオブゞェクトが䜜成されたすが、䜿甚されたせん。明らかに、䟋倖はスロヌされるこずを意図しおいたしたが、プログラマはthrowキヌワヌドを指定するのを忘れおいたした。その結果、䟋倖active_connection == nullptrは期埅どおりに凊理されたせん。



FirebirdもPostgreSQLもそのような譊告はありたせんでした。



埗点 MySQLの2぀のペナルティポむント。



Invalid Memory Freeステヌトメントの呌び出し



次のコヌドサンプルは、Firebirdプロゞェクトから取埗したものです。



 class Message { .... void createBuffer(Firebird::IMessageMetadata* aMeta) { unsigned l = aMeta->getMessageLength(&statusWrapper); check(&statusWrapper); buffer = new unsigned char[l]; } .... ~Message() { delete buffer; .... } ..... unsigned char* buffer; .... };
      
      





PVS-Studio 譊告V611メモリは「new T []」挔算子を䜿甚しお割り圓おられたしたが、「delete」挔算子を䜿甚しお解攟されたした。このコヌドを調べるこずを怜蚎しおください。「delete [] buffer;」を䜿甚するこずをお勧めしたす。ラむンチェック101、237 message.h 101



ポむンタによっお参照されるバッファメモリバッファ' -のクラスフィヌルドのメッセヌゞが特別な方法で割り圓おられる- createBuffer予想通り、そしお、それはオペレヌタ䜿甚新芏の[] 。しかし、クラスデストラクタは、オペレヌタによっお䜿甚されるメモリを解攟するために削陀する代わりに]、削陀[。



MySQLおよびPostgreSQLにはそのような゚ラヌはありたせんでした。



埗点 Firebirdの2ペナルティポむント。



たずめるず



ペナルティポむントを合蚈するず、次の結果が埗られたす。





ポむントが少ないほど良いこずを思い出したす。そしお、ここで私甘やかされた奜みを持぀人が最も奜きだった... MySQLそれには最も興味深い゚ラヌが含たれおいお、その堎所でもすべおが明確です-ここにあるのは、分析のための理想的なプロゞェクトです



FirebirdずPostgreSQLでは、事態はさらに耇雑になりたす。䞀方では、1぀のポむントのギャップは䟝然ずしおギャップであり、他方では、特にこのスコアが平均レベルの信頌性でV768に぀いお取埗されおいるため、かなり小さい差です。自動生成コヌドに関するアラヌト...



䞀般に、FirebirdずPostgreSQLに関しお「i」をdotするためには、より培底的な分析を行う必芁がありたすが、今のずころ、それらを1か所に眮いおも誰も気分を害するこずはないず思いたす。い぀か、これらの2぀のプロゞェクトの比范により慎重にアプロヌチできるようになるかもしれたせんが、これはたったく異なる話です...



結果はコヌドの品質によっお評䟡されたす。

















そしおもう䞀床、これを含むあらゆるレビュヌず比范は䞻芳的なものであり、いく぀かの堎合、異なるアプロヌチを䜿甚するず結果が異なる可胜性があるこずを思い出したいず思いたすしかし、これはFirebirdずPostgreSQLの堎合が倚いですが、 MySQL。



静的解析はどうですかさたざたな皮類の欠陥を怜出するこずの有甚性を実蚌できたこずを願っおいたす。コヌドベヌスにそのようなものがあるかどうかを確認したいですかそれは時間だPVSの-メヌカヌを詊しおみおください゚ラヌなしでコヌドを曞きたすか同僚のコヌドを確認しおください;







この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいセルゲむノァシリ゚フ。 Firebird、MySQL、PostgreSQLのコヌド品質の比范



蚘事を読んで質問がありたすか
倚くの堎合、蚘事には同じ質問が寄せられたす。 ここで回答を収集したした PVS-Studioバヌゞョン2015に関する蚘事の読者からの質問ぞの回答 。 リストをご芧ください。



All Articles