Санҷиши rdesktop ва xrdp бо истифода аз анализатори PVS-Studio

Санҷиши мизи корӣ ва xrdp бо истифода аз анализатори PVS-Studio
Ин баррасии дуввум дар як қатор мақолаҳо дар бораи санҷиши барномаҳои кушодаасос барои кор бо протоколи RDP мебошад. Дар он мо муштарии rdesktop ва сервери xrdp-ро дида мебароем.

Ҳамчун воситаи муайян кардани хатогиҳо истифода мешавад PVS-Студияи. Он як таҳлилгари рамзи статикӣ барои забонҳои C, C++, C# ва Java мебошад, ки дар платформаҳои Windows, Linux ва macOS дастрас аст.

Дар мақола танҳо он хатогиҳое оварда шудаанд, ки ба ман ҷолиб буданд. Бо вуҷуди ин, лоиҳаҳо хурд ҳастанд, бинобар ин, хатогиҳо кам буданд :).

эрод гирифтан. Мақолаи қаблиро дар бораи санҷиши лоиҳаи FreeRDP пайдо кардан мумкин аст дар ин ҷо.

мизи корӣ

мизи корӣ — татбиқи ройгони муштарии RDP барои системаҳои UNIX асосёфта. Он инчунин метавонад дар Windows истифода шавад, агар шумо лоиҳаро зери Cygwin созед. Иҷозатнома дар доираи GPLv3.

Ин муштарӣ хеле маъмул аст - он ба таври нобаёнӣ дар ReactOS истифода мешавад ва шумо инчунин метавонед барои он фронтҳои графикии тарафи сеюмро пайдо кунед. Бо вуҷуди ин, ӯ хеле пир аст: озодии аввалини ӯ 4 апрели соли 2001 рух дод - дар замони навиштан, ӯ 17-сола аст.

Тавре ки ман пештар қайд кардам, лоиҳа хеле хурд аст. Он тақрибан 30 ҳазор сатри кодро дар бар мегирад, ки бо назардошти синну солаш каме аҷиб аст. Барои муқоиса, FreeRDP дорои 320 ҳазор сатр аст. Ин аст натиҷаи барномаи Cloc:

Санҷиши мизи корӣ ва xrdp бо истифода аз анализатори PVS-Studio

Рамзи дастнорас

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 дар намуди char

V739 EOF набояд бо арзиши навъи "char" муқоиса карда шавад. '(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 мувофиқат мекунад, агар сухан дар бораи тағирёбандае ба монанди char. Маълум мешавад, ки рамзи 0xFF, мисли EOF (-1) ҳамчун охири файл шарҳ дода мешавад. Барои роҳ надодан ба чунин хатогиҳо, натиҷаи функсия аст fgetc бояд дар як тағирёбанда нигоҳ дошта шавад Int.

Хатогиҳо

Қисмати 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 Як қисми ифодаи шартӣ ҳамеша дуруст аст: add > 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 - амалисозии протокол. Дар доираи иҷозатномаи Apache 2.0 паҳн карда шудааст.
  • xorgxrdp - Маҷмӯи драйверҳои Xorg барои истифода бо xrdp. Литсензия - X11 (ба монанди MIT, аммо истифода дар таблиғро манъ мекунад)

Таҳияи лоиҳа ба натиҷаҳои rdesktop ва FreeRDP асос ёфтааст. Дар аввал, барои кор бо графика шумо бояд сервери алоҳидаи VNC ё сервери махсуси X11 бо дастгирии RDP - X11rdp -ро истифода баред, аммо бо пайдоиши xorgxrdp ниёз ба онҳо аз байн рафт.

Дар ин мақола мо xorgxrdp-ро фаро намегирем.

Лоиҳаи xrdp, мисли лоиҳаи қаблӣ, хеле хурд аст ва тақрибан 80 ҳазор сатрро дар бар мегирад.

Санҷиши мизи корӣ ва xrdp бо истифода аз анализатори PVS-Studio

Хатогиҳои бештар

V525 Рамз маҷмӯи блокҳои шабеҳро дар бар мегирад. Ҷузъҳои 'r', 'g', 'r'-ро дар сатрҳои 87, 88, 89 санҷед. 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 гирифта шудааст, ки кодеки jpeg2000-ро барои RemoteFX амалӣ мекунад. Дар ин ҷо, аз афташ, каналҳои графикии маълумот омехта шудаанд - ба ҷои ранги "кабуд", "сурх" сабт шудааст. Ин хато эҳтимолан дар натиҷаи нусхабардорӣ ба вуҷуд омадааст.

Ҳамин мушкилот дар як функсияи шабеҳ рух дод 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))
  {
    ....
  }
  ....
}

Функсия тағирёбандаи навъиро мехонад кӯтоҳи беимзо ба тағирёбанда монанд Int. Санҷиш дар ин ҷо лозим нест, зеро мо тағирёбандаи беимзоро мехонем ва натиҷаро ба тағирёбандаи калонтар таъин мекунем, бинобар ин тағирёбанда қимати манфӣ гирифта наметавонад.

Санҷишҳои нолозим

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-ро аз мо зеркашӣ кунед сомона.

Санҷиши мизи корӣ ва xrdp бо истифода аз анализатори PVS-Studio

Агар шумо хоҳед, ки ин мақоларо бо шунавандагони англисзабон мубодила кунед, лутфан истиноди тарҷумаро истифода баред: Сергей Ларин. Санҷиши rdesktop ва xrdp бо PVS-Studio

Манбаъ: will.com

Илова Эзоҳ