د PVS-Studio تحلیل کونکي په کارولو سره rdesktop او xrdp چک کول

د PVS-Studio تحلیل کونکي په کارولو سره rdesktop او xrdp چک کول
دا د RDP پروتوکول سره کار کولو لپاره د خلاصې سرچینې برنامو ازموینې په اړه د مقالو په لړۍ کې دویمه بیاکتنه ده. پدې کې به موږ د rdesktop پیرودونکي او xrdp سرور وګورو.

د غلطیو پیژندلو لپاره د یوې وسیلې په توګه کارول کیږي PVS- سټوډیو. دا د C، C++، C# او جاوا ژبو لپاره د جامد کوډ شنونکی دی، په وینډوز، لینکس او macOS پلیټ فارمونو کې شتون لري.

مقاله یوازې هغه تېروتنې وړاندې کوي چې ما ته په زړه پوري ښکاري. په هرصورت، پروژې کوچنۍ دي، نو لږې غلطۍ وې :).

تبصره. د FreeRDP پروژې تصدیق په اړه پخوانۍ مقاله موندل کیدی شي دلته.

rdesktop

rdesktop - د UNIX-based سیسټمونو لپاره د RDP پیرودونکي وړیا پلي کول. دا د وینډوز لاندې هم کارول کیدی شي که تاسو د Cygwin لاندې پروژه جوړه کړئ. د GPLv3 لاندې جواز لري.

دا پیرودونکی خورا مشهور دی - دا په ډیفالټ ReactOS کې کارول کیږي ، او تاسو کولی شئ د دې لپاره د دریمې ډلې ګرافیکي مخکیني پایونه هم ومومئ. په هرصورت، هغه ډیر زوړ دی: د هغه لومړی خوشې کول د اپریل په 4، 2001 کې ترسره شوي - د لیکلو په وخت کې، هغه 17 کلن دی.

لکه څنګه چې ما مخکې یادونه وکړه، پروژه ډیره کوچنۍ ده. دا د کوډ شاوخوا 30 زره لینونه لري، کوم چې د دې عمر په پام کې نیولو سره یو څه عجيب دی. د پرتله کولو لپاره، FreeRDP 320 زره لینونه لري. دلته د Cloc برنامې محصول دی:

د PVS-Studio تحلیل کونکي په کارولو سره rdesktop او xrdp چک کول

د لاسرسي وړ کوډ

V779 غیر موجود کوډ وموندل شو. دا ممکنه ده چې یوه تېروتنه شتون ولري. rdesktop.c 1502

int
main(int argc, char *argv[])
{
  ....
  return handle_disconnect_reason(deactivated, ext_disc_reason);

  if (g_redirect_username)
    xfree(g_redirect_username);

  xfree(g_username);
}

تېروتنه موږ سره په فنکشن کې سمدلاسه مخ کیږي اصلي: موږ ګورو چې کوډ د آپریټر وروسته راځي بېرته - دا ټوټه د حافظې پاکول ترسره کوي. په هرصورت، تېروتنه یو ګواښ نه رامنځته کوي: ټول تخصیص شوي حافظه به د پروګرام له وتلو وروسته د عملیاتي سیسټم لخوا پاک شي.

هیڅ غلطي اداره کول

V557 سرې زیرمه ممکنه ده. د 'n' شاخص ارزښت -1 ته رسیدلی شي. rdesktop.c 1872

RD_BOOL
subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
{
  int n = 1;
  char output[256];
  ....
  while (n > 0)
  {
    n = read(fd[0], output, 255);
    output[n] = ' '; // <=
    str_handle_lines(output, &rest, linehandler, data);
  }
  ....
}

په دې قضیه کې د کوډ ټوټه له فایل څخه بفر ته لوستل کیږي تر هغه چې فایل پای ته ورسیږي. په هرصورت، دلته هیڅ غلطی اداره کول شتون نلري: که یو څه غلط وي، نو بیا پاتې برخه -1 به بیرته راګرځي، او بیا به سرې له منځه یوسي محصول.

په چار ډول کې د EOF کارول

V739 EOF باید د 'چار' ډول ارزښت سره پرتله نشي. '(c = fgetc(fp))' باید د 'int' ډول وي. ctrl.c 500


int
ctrl_send_command(const char *cmd, const char *arg)
{
  char result[CTRL_RESULT_SIZE], c, *escaped;
  ....
  while ((c = fgetc(fp)) != EOF && index < CTRL_RESULT_SIZE && c != 'n')
  {
    result[index] = c;
    index++;
  }
  ....
}

دلته موږ د فایل پای ته رسیدو غلط اداره ګورو: که fgetc یو کرکټر بیرته راګرځوي چې کوډ یې 0xFF دی، دا به د فایل پای په توګه تشریح شي (EOF).

EOF دا یو ثابت دی، معمولا د -1 په توګه تعریف شوی. د مثال په توګه، په CP1251 کوډ کولو کې، د روسیې د الفبا وروستی لیک د 0xFF کوډ لري، کوم چې د -1 شمیرې سره مطابقت لري که چیرې موږ د یو متغیر په اړه خبرې وکړو لکه د چهار. دا معلومه شوه چې سمبول 0xFF، لکه EOF (-1) د فایل پای په توګه تشریح شوی. د داسې غلطیو څخه د مخنیوي لپاره، د فعالیت پایله ده fgetc باید په یو متغیر کې وساتل شي لکه اینټ.

ټایپوس

ټوټه 1

V547 د لیکلو وخت تل غلط دی. disk.c 805

RD_NTSTATUS
disk_set_information(....)
{
  time_t write_time, change_time, access_time, mod_time;
  ....
  if (write_time || change_time)
    mod_time = MIN(write_time, change_time);
  else
    mod_time = write_time ? write_time : change_time; // <=
  ....
}

شاید د دې کوډ لیکوال دا غلط ترلاسه کړي || и && په حالت کې راځئ چې د ارزښتونو لپاره ممکنه اختیارونه په پام کې ونیسو لیکل_ وخت и بدلون_وخت:

  • دواړه متغیرونه د 0 سره مساوي دي: پدې حالت کې به موږ په یوه څانګه کې پای ته ورسوو بل: متغیر mod_time د راتلونکي حالت په پام کې نیولو پرته به تل 0 وي.
  • یو له متغیرونو څخه 0 دی: mod_time د 0 سره به مساوي وي (په دې شرط چې بل متغیر غیر منفي ارزښت ولري)، ځکه MIN د دوو انتخابونو څخه به کوچنی غوره کړي.
  • دواړه متغیرونه د 0 سره مساوي ندي: لږترلږه ارزښت غوره کړئ.

کله چې د حالت سره ځای په ځای شي د لیکلو وخت او د بدلون وخت چلند به سم ښکاري:

  • یو یا دواړه متغیرونه د 0 سره مساوي ندي: یو غیر صفر ارزښت غوره کړئ.
  • دواړه متغیرونه د 0 سره مساوي ندي: لږترلږه ارزښت غوره کړئ.

ټوټه 2

V547 بیان تل ریښتیا وي. شاید '&&' آپریټر باید دلته وکارول شي. disk.c 1419

static RD_NTSTATUS
disk_device_control(RD_NTHANDLE handle, uint32 request, STREAM in,
      STREAM out)
{
  ....
  if (((request >> 16) != 20) || ((request >> 16) != 9))
    return RD_STATUS_INVALID_PARAMETER;
  ....
}

په ښکاره ډول چلونکي دلته هم ګډ شوي دي || и &&، یا == и !=: یو متغیر نشي کولی په ورته وخت کې 20 او 9 ارزښت ولري.

لا محدود لاین کاپي کول

V512 د 'sprintf' فنکشن زنګ به د بفر 'fullpath' د ډیریدو لامل شي. disk.c 1257

RD_NTSTATUS
disk_query_directory(....)
{
  ....
  char *dirname, fullpath[PATH_MAX];
  ....
  /* Get information for directory entry */
  sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
  ....
}

کله چې تاسو په بشپړ ډول فنکشن وګورئ، نو دا به روښانه شي چې دا کوډ ستونزې نه رامینځته کوي. په هرصورت ، دوی ممکن په راتلونکي کې رامینځته شي: یو بې پروایی بدلون او موږ به د بفر ډیر جریان ترلاسه کړو - سپرینټ د هیڅ شی لخوا محدود نه دی، نو کله چې د لارې نښلول موږ کولی شو د صف له حدودو هاخوا لاړ شو. دا سپارښتنه کیږي چې دې تلیفون ته پام وکړئ snprintf(پوره لاره، PATH_MAX، ....).

بې ځایه حالت

V560 د مشروط بیان یوه برخه تل ریښتیا وي: اضافه کړئ > 0. scard.c 507

static void
inRepos(STREAM in, unsigned int read)
{
  SERVER_DWORD add = 4 - read % 4;
  if (add < 4 && add > 0)
  {
    ....
  }
}

د تفتیش اضافه کړئ > 0 دلته اړتیا نشته: متغیر به تل له صفر څخه لوی وي، ځکه لوستل %4 د ویش پاتې برخه به بیرته راستانه کړي، مګر دا به هیڅکله د 4 سره مساوي نه وي.

xrdp

xrdp - د خلاصې سرچینې کوډ سره د RDP سرور پلي کول. پروژه په 2 برخو ویشل شوې ده:

  • xrdp - د پروتوکول پلي کول. د اپاچی 2.0 جواز لاندې توزیع شوی.
  • xorgxrdp - د xrdp سره د کارولو لپاره د Xorg ډرایورونو سیټ. جواز - X11 (لکه MIT، مګر په اعلاناتو کې کارول منع کوي)

د پروژې پراختیا د rddesktop او FreeRDP پایلو پر بنسټ والړ ده. په پیل کې، د ګرافیک سره کار کولو لپاره، تاسو باید یو جلا VNC سرور، یا د RDP ملاتړ سره یو ځانګړی X11 سرور وکاروئ - X11rdp، مګر د xorgxrdp په راتګ سره، د دوی اړتیا ورکه شوه.

پدې مقاله کې به موږ xorgxrdp پوښ نه کړو.

د xrdp پروژه، د تیرې په څیر، ډیره کوچنۍ ده او نږدې 80 زره لینونه لري.

د PVS-Studio تحلیل کونکي په کارولو سره rdesktop او xrdp چک کول

نور ټایپونه

V525 کوډ د ورته بلاکونو ټولګه لري. په 87، 88، 89 کرښو کې توکي 'r', 'g', 'r' وګورئ. rfxencode_rgb_to_yuv.c 87

static int
rfx_encode_format_rgb(const char *rgb_data, int width, int height,
                      int stride_bytes, int pixel_format,
                      uint8 *r_buf, uint8 *g_buf, uint8 *b_buf)
{
  ....
  switch (pixel_format)
  {
    case RFX_FORMAT_BGRA:
      ....
      while (x < 64)
      {
          *lr_buf++ = r;
          *lg_buf++ = g;
          *lb_buf++ = r; // <=
          x++;
      }
      ....
  }
  ....
}

دا کوډ د librfxcodec کتابتون څخه اخیستل شوی، کوم چې د RemoteFX لپاره jpeg2000 کوډیک پلي کوي. دلته، په ښکاره ډول، د ګرافیک ډیټا چینلونه مخلوط شوي - د "نیلي" رنګ پرځای، "سور" ثبت شوی. دا تېروتنه غالباً د کاپي پیسټ په پایله کې راڅرګنده شوه.

ورته ستونزه په ورته فعالیت کې رامنځ ته شوه rfx_encode_format_argb، کوم چې شنونکي موږ ته هم وویل:

V525 کوډ د ورته بلاکونو ټولګه لري. توکي 'a'، 'r'، 'g'، 'r' په 260، 261، 262، 263 کرښو کې وګورئ. rfxencode_rgb_to_yuv.c 260

while (x < 64)
{
    *la_buf++ = a;
    *lr_buf++ = r;
    *lg_buf++ = g;
    *lb_buf++ = r;
    x++;
}

د صف اعالمیه

V557 د سرې زیاتیدل ممکن دي. د 'i - 8' شاخص ارزښت 129 ته رسیدلی شي. genkeymap.c 142

// evdev-map.c
int xfree86_to_evdev[137-8+1] = {
  ....
};

// genkeymap.c
extern int xfree86_to_evdev[137-8];

int main(int argc, char **argv)
{
  ....
  for (i = 8; i <= 137; i++) /* Keycodes */
  {
    if (is_evdev)
        e.keycode = xfree86_to_evdev[i-8];
    ....
  }
  ....
}

په دې دوو فایلونو کې د صف اعلان او تعریف متضاد دي - اندازه یې د 1 لخوا توپیر لري. په هرصورت، هیڅ غلطی نه پیښیږي - سمه اندازه په evdev-map.c فایل کې مشخص شوې، نو د حد څخه بهر شتون نلري. نو دا یوازې یو بګ دی چې په اسانۍ سره حل کیدی شي.

ناسم پرتله کول

V560 د مشروط بیان یوه برخه تل غلط وي: (cap_len <0). xrdp_caps.c 616

// common/parse.h
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
#define in_uint16_le(s, v) do 
....
#else
#define in_uint16_le(s, v) do 
{ 
    (v) = *((unsigned short*)((s)->p)); 
    (s)->p += 2; 
} while (0)
#endif

int
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
{
  int cap_len;
  ....
  in_uint16_le(s, cap_len);
  ....
  if ((cap_len < 0) || (cap_len > 1024 * 1024))
  {
    ....
  }
  ....
}

فنکشن یو ډول متغیر لوستل کوي لنډ لنډیز په یو متغیر لکه اینټ. دلته چک کولو ته اړتیا نشته ځکه چې موږ یو نه لاسلیک شوی متغیر لوستلو او پایله یې لوی متغیر ته وړاندې کوو، نو متغیر نشي کولی منفي ارزښت واخلي.

غیر ضروري چکونه

V560 د مشروط بیان یوه برخه تل ریښتیا ده: (bpp! = 16). libxrdp.c 704

int EXPORT_CC
libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
                     char *data, char *mask, int x, int y, int bpp)
{
  ....
  if ((bpp == 15) && (bpp != 16) && (bpp != 24) && (bpp != 32))
  {
      g_writeln("libxrdp_send_pointer: error");
      return 1;
  }
  ....
}

د نابرابرۍ چیکونه دلته معنی نلري ځکه چې موږ دمخه په پیل کې پرتله کوو. احتمال لري چې دا یو ټایپ وي او پراختیا کونکي غوښتل چې آپریټر وکاروي || د ناسمو دلیلونو د فلټر کولو لپاره.

پایلې

د پلټنې په جریان کې، هیڅ جدي غلطی ندی پیژندل شوی، مګر ډیری نیمګړتیاوې وموندل شوې. په هرصورت، دا ډیزاینونه په ډیری سیسټمونو کې کارول کیږي، که څه هم په ساحه کې کوچني دي. یوه کوچنۍ پروژه اړینه نه ده چې ډیری غلطی ولري، نو تاسو باید یوازې د وړو پروژو په اړه د تحلیل کونکي فعالیت قضاوت ونه کړئ. تاسو کولی شئ پدې اړه نور په مقاله کې ولولئ "احساسات چې د شمیرو لخوا تایید شوي".

تاسو کولی شئ زموږ څخه د PVS-Studio آزموینې نسخه ډاونلوډ کړئ سایټ.

د PVS-Studio تحلیل کونکي په کارولو سره rdesktop او xrdp چک کول

که تاسو غواړئ دا مقاله د انګلیسي ژبو لیدونکو سره شریکه کړئ، مهرباني وکړئ د ژباړې لینک وکاروئ: سرګي لارین. د PVS-Studio سره rddesktop او xrdp چک کول

سرچینه: www.habr.com

Add a comment