PVS-Studioを䜿甚したGIMP゜ヌスコヌドの確認

PVS-StudioおよびGIMP

GIMPをテストするには、たずコンパむルする方法を孊ぶ必芁がありたす。 これは、怜蚌が数回延期されたため、簡単な䜜業ではありたせん。 ただし、このプロゞェクトは有名で、゜ヌスコヌドの品質を評䟡するこずは興味深いです。 したがっお、怠lazは砎られ、プロゞェクトが分析されたした。



ギンプ



時々このグラフィカル゚ディタヌを䜿甚したすが、 GIMPむンタヌフェむスは奜きではありたせん。 月に数回、次の蚘事にナニコヌンの写真を合わせるためだけにPhotoshopを賌入するのは意味がありたせん。 ペむントずGIMPで十分です。



私は、利䟿性を刀断するのに十分なプロナヌザヌではないず蚀えたす。 しかし、爪が出おいるために怅子に座るのは䞍快だず䞻匵するために、倧工や家具の専門家である必芁はたったくありたせん。 GIMPには、気になる倚くの欠陥がリストされおいたす。 たずえば、ファむルを開くずきに、ロシア語の文字がパスに含たれおいる堎合、[堎所]フィヌルドにファむルぞのフルパスを挿入できたせん。 このような倚くの欠点がありたす。



䞍噚甚なGIMPむンタヌフェヌスに粟通しおいるので、コヌドに倚くの間違いがあるこずを期埅しおいたした。 私は間違っおいたした。 開発者はすでに仕事で静的解析を䜿甚しおいるこずがわかりたす。 さらに、圌らは重砲を䜿甚したす。 最も匷力な静的アナラむザヌの1぀であるCoverityを䜿甚したす。



Coverityが䜿甚されおいるずいう事実は、むンタヌネットぞの参照によっお刀断したす。



米囜政府の支揎を受けお組織され、オヌプン゜ヌスプログラムの゚ラヌの調査に取り組んだCoverityプロゞェクトは、チェックされたプロゞェクトのリストには、人気のあるScribus、GIMP、Inkscape、Krita、Blenderなど、グラフィックスを操䜜するための玄100のアプリケヌションが含たれるず報告しおいたす2007幎の出版物から。



怜蚌結果



Coverityの埌にGIMPコヌドで䜕が芋぀かるか芋おみたしょう。 分析は、 PVS-Studioバヌゞョン5.18を䜿甚しお実行されたした。



フラグメントN1-N3

typedef double gdouble; GimpBlob * gimp_blob_square (gdouble xc, gdouble yc, gdouble xp, gdouble yp, gdouble xq, gdouble yq) { GimpBlobPoint points[4]; /* Make sure we order points ccw */ if (xp * yq - yq * xp < 0) { xq = -xq; yq = -yq; } .... }
      
      





PVS-Studio譊告V501 '-'挔算子の巊右に同じ副次匏がありたすxp * yq-yq * xp gimpink-blob.c 162



「xp * yq-yq * xp」ずいう衚珟は非垞に奇劙です。 倀「xp * yq」は、それ自䜓から枛算されたす。



同䞀のチェックは、このファむルの少し䞋にありたす。 行195および278。



フラグメントN4

 gint64 gimp_g_value_get_memsize (GValue *value) { .... GimpArray *array = g_value_get_boxed (value); if (array) memsize += (sizeof (GimpArray) + array->static_data ? 0 : array->length); .... }
      
      





è­Šå‘ŠPVS-StudioV502「」挔算子は、予想ずは異なる方法で動䜜する可胜性がありたす。 「」挔算子は、「+」挔算子よりも優先床が䜎くなりたす。 gimp-utils.c 233



オペレヌタヌの優先順䜍に関する混乱。 特定のオブゞェクトのサむズに、0たたは「array-> length」を远加する必芁がありたす。 ただし、「+」挔算子の優先順䜍は「」挔算子よりも高くなっおいたす。 匏は次のように機胜したす。

 memsize += ((sizeof (GimpArray) + array->static_data) ? 0 : array->length);
      
      





おそらくプログラマヌはこれを知っおいたので、括匧を䜿甚したした。 しかし、その埌、ブラケットは適切ではありたせん。 正しいオプション

 memsize += sizeof (GimpArray) + (array->static_data ? 0 : array->length);
      
      





フラグメントN5、N6

 #define cmsFLAGS_NOOPTIMIZE 0x0100 #define cmsFLAGS_BLACKPOINTCOMPENSATION 0x2000 static void lcms_layers_transform_rgb (...., gboolean bpc) { .... transform = cmsCreateTransform ( src_profile, lcms_format, dest_profile, lcms_format, intent, cmsFLAGS_NOOPTIMIZE | bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0); .... }
      
      





è­Šå‘ŠPVS-StudioV502「」挔算子は、予想ずは異なる方法で動䜜する可胜性がありたす。 「」挔算子の優先順䜍は「|」よりも䜎い 挔算子。 lcms.c 1016



倉数「bpc」に応じお、フラグ「cmsFLAGS_BLACKPOINTCOMPENSATION」たたはフラグ「cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_NOOPTIMIZE "。



挔算子の優先床「|」 䞉項挔算子「」の優先床よりも高い。 その結果、「?:」挔算子の条件は匏「cmsFLAGS_NOOPTIMIZE | bpc。」 この条件は垞に真です。 cmsFLAGS_BLACKPOINTCOMPENSATIONフラグは垞に関数に枡されたす。



正しいオプション

 transform = cmsCreateTransform ( src_profile, lcms_format, dest_profile, lcms_format, intent, cmsFLAGS_NOOPTIMIZE | (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0));
      
      





同様の゚ラヌは、lcms.c 1016にありたす。



フラグメントN7

 static gint load_resource_lrfx (....) { .... else if (memcmp (effectname, "oglw", 4) == 0) <<<=== .... else if (memcmp (effectname, "iglw", 4) == 0) .... else if (memcmp (effectname, "oglw", 4) == 0) <<<=== .... else if (memcmp (effectname, "bevl", 4) == 0) .... }
      
      





PVS-Studio譊告V517「ifA{...} else ifA{...}」パタヌンの䜿甚が怜出されたした。 論理゚ラヌが存圚する可胜性がありたす。 行を確認しおください602、688。psd-layer-res-load.c 602



シヌケンスif-elseif-elseif-の2぀の同䞀条件...



フラグメントN8

 void gimp_text_get_transformation (GimpText *text, GimpMatrix3 *matrix) { g_return_if_fail (GIMP_IS_TEXT (text)); g_return_if_fail (matrix != NULL); matrix->coeff[0][0] = text->transformation.coeff[0][0]; matrix->coeff[0][1] = text->transformation.coeff[0][1]; matrix->coeff[0][2] = text->offset_x; matrix->coeff[1][0] = text->transformation.coeff[1][0]; matrix->coeff[1][1] = text->transformation.coeff[1][1]; matrix->coeff[1][2] = text->offset_y; matrix->coeff[2][0] = 0.0; matrix->coeff[2][1] = 0.0; matrix->coeff[2][1] = 1.0; <<<=== }
      
      





PVS-Studioの譊告V519 'matrix-> coeff [2] [1]'倉数には倀が2回連続しお割り圓おられたす。 おそらくこれは間違いです。 行を確認しおください567、568。gimptext.c 568



最埌の行の効果 。 最埌に、間違ったむンデックスが䜿甚されたす。 する必芁がありたす

 matrix->coeff[2][0] = 0.0; matrix->coeff[2][1] = 0.0; matrix->coeff[2][2] = 1.0;
      
      





フラグメントN9

 static void warp_one (....) { .... if (first_time) gimp_pixel_rgn_init (&dest_rgn, new, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE); else gimp_pixel_rgn_init (&dest_rgn, new, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE); .... }
      
      





PVS-Studio譊告V523「then」ステヌトメントは「else」ステヌトメントず同等です。 warp.c 1366



条件に関係なく同じアクションが実行されるこずは疑わしいです。



フラグメントN10、N11、N​​12

 gboolean gimp_wire_read (GIOChannel *channel, guint8 *buf, gsize count, gpointer user_data) { g_return_val_if_fail (count >= 0, FALSE); .... }
      
      





PVS-Studio譊告V547匏 'count> = 0'は垞にtrueです。 笊号なしの型の倀は垞に> = 0です。gimpwire.c 99



「count> = 0」をチェックしおも意味がありたせん。倉数「count」は笊号なしだからです。 これは重倧な間違いではないかもしれたせんが、蚀及する䟡倀がありたす。



同様のチェックgimpwire.c 170; gimpcageconfig.c 428。



V547蚺断を䜿甚しお芋぀かったより興味深いケヌスに぀いおは、以䞋で説明したす。



フラグメントN13

 static GimpPlugInImageType image_types_parse (const gchar *name, const gchar *image_types) { .... while (*image_types && ((*image_types != ' ') || (*image_types != '\t') || (*image_types != ','))) { image_types++; } .... }
      
      





譊告V547匏は垞に真です。 ここでは、おそらく「&&」挔算子を䜿甚する必芁がありたす。 gimppluginprocedure.c 808



明確にするため、人為的な䟋を説明したす。

 int A = ...; if ( A != 1 || A != 2 || A != 3)
      
      





倉数Aが䜕であれ、条件は垞に満たされたす。



フラグメントN14

 static gunichar basic_inchar(port *pt) { .... gunichar c; .... c = g_utf8_get_char_validated(pt->rep.string.curr, len); if (c >= 0) /* Valid UTF-8 character? */ { len = g_unichar_to_utf8(c, NULL); pt->rep.string.curr += len; return c; } /* Look for next valid UTF-8 character in buffer */ pt->rep.string.curr = g_utf8_find_next_char( pt->rep.string.curr, pt->rep.string.past_the_end); .... }
      
      





PVS-Studio譊告V547匏 'c> = 0'は垞にtrueです。 笊号なしの型の倀は垞に> = 0です。scheme.c 1654



すべおの文字は有効なUTF-8文字ず芋なされたす。 倉数 'c​​'には笊号なしの型がありたす。 したがっお、条件c> = 0は垞に真です。



フラグメントN15

 #define ABS(a) (((a) < 0) ? -(a) : (a)) static gint32 load_thumbnail (...., gint32 thumb_size, ....) { .... guint32 size; guint32 diff; .... diff = ABS(thumb_size - size); .... }
      
      





PVS-Studio譊告V547匏 'thumb_size-size<0'は垞にfalseです。 笊号なしの型の倀が<0になるこずはありたせんfile-xmc.c 874



プログラムは、プログラマが意図したずおりに機胜したせん。 倉数 'thumb_size'が10で、倉数 'size'が25であるずしたす。



䞀芋、蚈算の結果は15になりそうです。実際、結果は0xFFFFFFF14294967281になりたす。



匏「thumb_size-size」には笊号なしの型がありたす。 その結果、数字0xFFFFFFF1uを取埗したす。 この堎合、ABSマクロは䜕もしたせん。



フラグメントN16

 static gchar * script_fu_menu_map (const gchar *menu_path) { .... const gchar *suffix = menu_path + strlen (mapping[i].old); if (! *suffix == '/') continue; .... }
      
      





PVS-Studio譊告V562 0たたは1を倀47ず比范するのは奇劙です!! *サフィックス== '/'。 script-fu-scripts.c 859



繰り返したすが、操䜜の優先順䜍。 最初に、匏「*サフィックス」が評䟡されたす。 その結果、0たたは1が埗られたす。この0たたは1は '/'文字ず比范されたすが、これは意味がありたせん。



正しいオプション

 if (*suffix != '/')
      
      





フラグメントN17

 static void save_file_chooser_response (GtkFileChooser *chooser, gint response_id, GFigObj *obj) { .... gfig_context->current_obj = obj; gfig_save_callbk (); gfig_context->current_obj = gfig_context->current_obj; .... }
      
      





PVS-Studioの譊告V570 'gfig_context-> current_obj'倉数はそれ自䜓に割り圓おられたす。 gfig-dialog.c 1623



倉数は自分自身にコピヌされたす。



フラグメントN18

 size g_strlcpy(gchar *dest, const gchar *src, gsize dest_size); GList * gimp_brush_generated_load (....) { .... gchar *string; .... /* the empty string is not an allowed name */ if (strlen (string) < 1) g_strlcpy (string, _("Untitled"), sizeof (string)); .... }
      
      





è­Šå‘ŠPVS_StudioV579 g_strlcpy関数は、ポむンタヌずそのサむズを匕数ずしお受け取りたす。 間違いかもしれたせん。 3番目の匕数を調べたす。 gimpbrushgenerated-load.c 119



sizeof文字列挔算子は、バッファヌのサむズではなく、ポむンタヌのサむズを蚈算したす。



フラグメントN19

 static gboolean save_image (....) { .... gint c; .... if (has_alpha && (data[rowoffset + k + 1] < 128)) c |= 0 << (thisbit ++); else .... }
      
      





PVS-Studio譊告V684倉数「c」の倀は倉曎されたせん。 匏を調べるこずを怜蚎しおください。 「0」ではなく「1」が存圚する可胜性がありたす。 file-xbm.c 1136



匏 "c | = 0 <<thisbit ++;"は、倉数 'c​​'の倀を倉曎したせん。



私の芳察では、そのようなコヌドは特定のビットをリセットしたかったが、間違っおいたずきに芋぀けるこずができたす。 この堎合、コヌドは次のようになりたす。

 c &= ~(1u << (thisbit ++));
      
      





フラグメントN20

 gboolean gimp_item_get_popup_size (...., gint *popup_width, gint *popup_height) { .... if (scaling_up) { *popup_width = gimp_item_get_width (item); *popup_width = gimp_item_get_height (item); } .... }
      
      





PVS-Studio譊告V537「popup_width」アむテムの䜿甚の正確さを確認するこずを怜蚎しおください。 gimpitem-preview.c 126



入力ミスたたは結果のコピヌペヌスト。 正しいオプション

 *popup_width = gimp_item_get_width (item); *popup_height = gimp_item_get_height (item);
      
      





フラグメントN21

 gboolean gimp_draw_tool_on_vectors_curve (...., GimpAnchor **ret_segment_start, GimpAnchor **ret_segment_end, ....) { .... if (ret_segment_start) *ret_segment_start = NULL; if (ret_segment_start) *ret_segment_end = NULL; .... }
      
      





PVS-Studio譊告V581互いに䞊んでいる「if」挔算子の条件匏は同䞀です。 チェック行1212、1213。gimpdrawtool.c 1213



入力ミスたたは結果のコピヌペヌスト。 正しいオプション

 if (ret_segment_start) *ret_segment_start = NULL; if (ret_segment_end) *ret_segment_end = NULL;
      
      





フラグメントN22-N40

 ObjectList_t* object_list_append_list(ObjectList_t *des, ObjectList_t *src) { GList *p; for (p = src->list; p; p = p->next) object_list_append(des, object_clone((Object_t*) p->data)); object_list_set_changed(des, (src) ? TRUE : FALSE); return des; }
      
      





PVS-Studio譊告V595 nullsrcに察しお怜蚌される前に、「src」ポむンタヌが䜿甚されたした。 行を確認しおください536、538。imap_object.c 536



「srcTRUEFALSE」ずいう条件から、ポむンタ「src」はnullptrず等しくなるず結論付けるこずができたす。



ただし、このポむンタヌは匏「p = src-> list」で倧胆に逆参照されおいたすが、これぱラヌです。



è­Šå‘ŠV595が発行される堎所は他にもありたす。 これらの堎所も確認する必芁がありたす。

おわりに



芋぀かった゚ラヌの重倧床を刀断するこずは困難です。 蚘事のおかげで䜕かが修正されたら嬉しいです。



私が蚀ったように、GIMPむンタヌフェヌスは奜きではありたせんが、開発者の䜜業に非垞に感謝しおいたす。 GIMPの蚘事の写真をたくさん䜜りたした。 ありがずう



この蚘事は英語です。



この蚘事を英語圏の聎衆ず共有したい堎合は、翻蚳ぞのリンクを䜿甚しおくださいAndrey Karpov。 PVS-StudioでGIMPの゜ヌスコヌドを確認したす。



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




All Articles