A’ sgrùdadh rdesktop agus xrdp leis an anailisiche PVS-Studio

A’ sgrùdadh rdesktop agus xrdp a’ cleachdadh an anailisiche PVS-Studio
Is e seo an dàrna lèirmheas ann an sreath de artaigilean mu bhith a’ dèanamh deuchainn air prògraman stòr fosgailte airson a bhith ag obair leis a’ phròtacal RDP. An seo seallaidh sinn ris a’ chleachdaiche rdesktop agus am frithealaiche xrdp.

Air a chleachdadh mar inneal gus mearachdan aithneachadh PVS-Studio'S e inneal-anailis còd statach a th' ann airson C, C++, C# agus Java, ri fhaighinn air àrd-ùrlaran Windows, Linux и macOS.

Chan eil an artaigil a’ nochdadh ach na mearachdan sin a bha a’ coimhead inntinneach dhomh. Ach, tha na pròiseactan beag, agus mar sin cha robh mòran mhearachdan ann :).

thuirt. Gheibhear artaigil roimhe mu dhearbhadh pròiseact FreeRDP an seo.

deasg

deasg — свободная реализация клиента RDP для UNIX-based систем. Его также можно использовать и под Windows, если собирать проект под Cygwin. Лицензирован под GPLv3.

Tha fèill mhòr air an neach-dèiligidh seo - tha e air a chleachdadh gu bunaiteach ann an ReactOS, agus gheibh thu cuideachd cinn-aghaidh grafaigeach treas-phàrtaidh air a shon. Ach, tha e gu math sean: chaidh a 'chiad fhoillseachadh aige a chumail air 4 Giblean, 2001 - aig àm sgrìobhaidh, tha e 17 bliadhna a dh'aois.

Mar a thuirt mi na bu thràithe, tha am pròiseact gu math beag. Tha timcheall air 30 mìle loidhne de chòd ann, rud a tha car neònach a’ beachdachadh air an aois. Airson coimeas a dhèanamh, tha 320 mìle loidhne ann an FreeRDP. Seo toradh a’ phrògram Cloc:

A’ sgrùdadh rdesktop agus xrdp a’ cleachdadh an anailisiche PVS-Studio

Còd neo-ruigsinneach

V779 Còd nach eil ri fhaighinn air a lorg. Tha e comasach gu bheil mearachd an làthair. 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);
}

Bidh a’ mhearachd a’ tighinn tarsainn oirnn sa bhad sa ghnìomh prìomh: chì sinn an còd a 'tighinn às deidh a' ghnìomhaiche air ais - bidh am pìos seo a’ glanadh cuimhne. Ach, chan eil am mearachd na chunnart: thèid a h-uile cuimhne a chaidh a thoirt seachad a ghlanadh leis an t-siostam obrachaidh às deidh don phrògram falbh.

Gun làimhseachadh mearachd

V557 Tha e comasach fo-thalamh Array. Dh’ fhaodadh luach clàr-amais ‘n’ ruighinn -1. deasg.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);
  }
  ....
}

Bidh an criomag còd sa chùis seo a’ leughadh bhon fhaidhle gu bufair gus an tig am faidhle gu crìch. Ach, chan eil làimhseachadh mearachd an seo: ma thèid rudeigin ceàrr, an uairsin leughadh tillidh e -1, agus an uairsin thèid an t-sreath thairis air Sgaoileadh.

A’ cleachdadh EOF ann an seòrsa char

V739 Cha bu chòir coimeas a dhèanamh eadar EOF agus luach den t-seòrsa 'char'. Bu chòir gum biodh an '(c = fgetc(fp))' den t-seòrsa '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++;
  }
  ....
}

An seo chì sinn làimhseachadh ceàrr air ruighinn deireadh an fhaidhle: ma tha fgetc a 'tilleadh caractar aig a bheil còd 0xFF, thèid a mhìneachadh mar deireadh an fhaidhle (EOF).

EOF tha e seasmhach, mar as trice air a mhìneachadh mar -1. Mar eisimpleir, anns a 'chòdachadh CP1251, tha an còd 0xFF aig an litir mu dheireadh den aibidil Ruiseanach, a tha a' freagairt ris an àireamh -1 ma tha sinn a 'bruidhinn mu dheidhinn caochladair mar Char. Tha e a 'tionndadh a-mach gu bheil an samhla 0xFF, mar EOF (-1) air a mhìneachadh mar deireadh an fhaidhle. Gus mearachdan mar sin a sheachnadh, is e toradh an gnìomh fgetc bu chòir a stòradh ann an caochladair mar int.

Typos

Earrann 1

V547 Tha abairt ‘write_time’ an-còmhnaidh meallta. diosc.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; // <=
  ....
}

Is dòcha gun d’ fhuair ùghdar a’ chòd seo ceàrr e || и && ann an staid. Beachdaichidh sinn air luachan comasach sgrìobhadh_àm и atharrachadh_àm:

  • Tha an dà chaochladair co-ionann ri 0: sa chùis seo bidh sinn a 'crìochnachadh ann am meur eile: caochladair mod_àm bidh e an-còmhnaidh 0 ge bith dè an suidheachadh a thig às.
  • Is e aon de na caochladairean 0: mod_àm bidh e co-ionann ri 0 (fhad 's gu bheil luach neo-àicheil aig a' chaochladair eile), oir min taghaidh am fear as lugha den dà roghainn.
  • Chan eil an dà chaochladair co-ionann ri 0: tagh an luach as ìsle.

Nuair a thèid an suidheachadh a chuir na àite write_time && change_time seallaidh an giùlan ceart:

  • Chan eil caochladair aon no an dà chuid co-ionann ri 0: tagh luach neo-neoni.
  • Chan eil an dà chaochladair co-ionann ri 0: tagh an luach as ìsle.

Earrann 2

V547 Tha an abairt an-còmhnaidh fìor. Is dòcha gum bu chòir an gnìomhaiche '&&' a chleachdadh an seo. diosg.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;
  ....
}

Tha e coltach gu bheil na gnìomhaichean measgaichte an seo cuideachd || и &&, no == и !=: Chan fhaod an luach 20 agus 9 a bhith aig caochladair aig an aon àm.

Leth-bhreac loidhne gun chrìoch

V512 Leanaidh gairm den ghnìomh ‘sprintf’ gu bhith a’ cur thairis air a’ bhufair ‘fullpath’. diosg.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);
  ....
}

Nuair a choimheadas tu air a’ ghnìomh gu h-iomlan, bidh e soilleir nach adhbhraich an còd seo duilgheadasan. Ach, faodaidh iad èirigh san àm ri teachd: aon atharrachadh gun chùram agus gheibh sinn bufair thar-shruth - sprintf Chan eil e air a chuingealachadh le rud sam bith, agus mar sin nuair a bhios sinn a’ co-chruinneachadh slighean faodaidh sinn a dhol seachad air crìochan an t-sreath. Thathas a’ moladh a bhith mothachail air a ’ghairm seo snprintf(làn-shlighe, PATH_MAX, ....).

Suidheachadh gun fheum

V560 Tha pàirt de mhìneachadh cumhach an-còmhnaidh fìor: cuir > 0. scard.c 507

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

sgrùdadh cuir > 0 chan eil feum air an seo: bidh an caochladair an-còmhnaidh nas motha na neoni, oir leugh % ​​4 tillidh e an còrr den roinn, ach cha bhi e gu bràth co-ionann ri 4.

xrdp

xrdp - buileachadh frithealaiche RDP le còd stòr fosgailte. Tha am pròiseact air a roinn ann an 2 phàirt:

  • xrdp - buileachadh protocol. Air a chuairteachadh fo chead Apache 2.0.
  • xorgxrdp - Seata de dhraibhearan Xorg airson an cleachdadh le xrdp. Cead - X11 (mar MIT, ach a’ toirmeasg cleachdadh ann an sanasachd)

Tha leasachadh a’ phròiseict stèidhichte air toraidhean rdesktop agus FreeRDP. An toiseach, gus obrachadh le grafaigean, bha agad ri frithealaiche VNC air leth a chleachdadh, no frithealaiche X11 sònraichte le taic RDP - X11rdp, ach le teachd xorgxrdp, dh’ fhalbh an fheum air an son.

San artaigil seo cha bhith sinn a’ còmhdach xorgxrdp.

Tha am pròiseact xrdp, mar an tè roimhe, glè bheag agus tha timcheall air 80 mìle loidhne ann.

A’ sgrùdadh rdesktop agus xrdp a’ cleachdadh an anailisiche PVS-Studio

Tuilleadh typos

V525 Anns a’ chòd tha cruinneachadh de bhlocaichean coltach ris. Thoir sùil air nithean 'r', 'g', 'r' ann an loidhnichean 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++;
      }
      ....
  }
  ....
}

Chaidh an còd seo a thoirt bhon leabharlann librfxcodec, a bhios a’ buileachadh an codec jpeg2000 airson RemoteFX. An seo, a rèir choltais, tha na seanailean dàta grafaigeach air an measgachadh - an àite an dath “gorm”, tha “dearg” air a chlàradh. Tha e coltach gun do nochd a’ mhearachd seo mar thoradh air lethbhreac-pas.

Thachair an aon dhuilgheadas ann an gnìomh coltach ris rfx_encode_format_argb, a dh’ innis an anailisiche dhuinn cuideachd:

V525 Anns a’ chòd tha cruinneachadh de bhlocaichean coltach ris. Thoir sùil air nithean 'a', 'r', 'g', 'r' ann an loidhnichean 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++;
}

Dearbhadh Array

V557 Tha e comasach faighinn thairis air Array. Dh’ fhaodadh luach clàr-amais ‘i — 8’ ruighinn 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];
    ....
  }
  ....
}

Tha dearbhadh agus mìneachadh an t-sreath anns an dà fhaidhle seo neo-fhreagarrach - tha am meud eadar-dhealaichte le 1. Ach, chan eil mearachdan ann - tha am meud ceart air a shònrachadh anns an fhaidhle evdev-map.c, agus mar sin chan eil crìochan ann. Mar sin is e seo dìreach bug a tha furasta a rèiteachadh.

Coimeas ceàrr

V560 Tha pàirt de mhìneachadh cumhach an-còmhnaidh meallta: (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))
  {
    ....
  }
  ....
}

Bidh an gnìomh a’ leughadh caochladair seòrsa goirid gun ainm ann an caochladair mar int. Chan eil feum air sgrùdadh an seo oir tha sinn a 'leughadh caochladair gun ainm agus a' sònrachadh an toraidh gu caochladair nas motha, agus mar sin chan urrainn don chaochladair luach àicheil a ghabhail.

Sgrùdaidhean neo-riatanach

V560 Tha pàirt de mhìneachadh cumhach an-còmhnaidh fìor: (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;
  }
  ....
}

Chan eil sgrùdaidhean neo-ionannachd a’ dèanamh ciall an seo leis gu bheil coimeas againn mu thràth aig an toiseach. Tha e coltach gur e typo a tha seo agus bha an leasaiche airson an gnìomhaiche a chleachdadh || gus argamaidean neo-dhligheach a shìoladh.

co-dhùnadh

Rè an sgrùdaidh, cha deach droch mhearachdan a chomharrachadh, ach chaidh mòran easbhaidhean a lorg. Ach, tha na dealbhaidhean sin air an cleachdadh ann an iomadh siostam, ged a tha iad beag ann an raon. Mar as trice chan eil mòran mhearachdan aig pròiseact beag, agus mar sin cha bu chòir dhut breithneachadh a dhèanamh air coileanadh an anailisiche a-mhàin air pròiseactan beaga. Faodaidh tu barrachd a leughadh mu dheidhinn seo san artaigil “Faireachdainnean a chaidh a dhearbhadh le àireamhan".

Faodaidh tu tionndadh deuchainn de PVS-Studio a luchdachadh sìos bhuainn làrach.

A’ sgrùdadh rdesktop agus xrdp a’ cleachdadh an anailisiche PVS-Studio

Ma tha thu airson an artaigil seo a cho-roinn le luchd-èisteachd Beurla, cleachd an ceangal eadar-theangachaidh: Sergey Larin. A’ sgrùdadh rdesktop agus xrdp le PVS-Studio

Source: www.habr.com

Ceannaich aoigheachd earbsach airson làraich le dìon DDoS, frithealaichean VPS VDS 🔥 Ceannaich aoigheachd làrach-lìn earbsach le dìon DDoS, frithealaichean VPS VDS | ProHoster