
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 '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 .
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:

Còd neo-ruigsinneach
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
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
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
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
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
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
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
- 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.

Tuilleadh typos
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:
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
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
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
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 “".
Faodaidh tu tionndadh deuchainn de PVS-Studio a luchdachadh sìos bhuainn .
Ma tha thu airson an artaigil seo a cho-roinn le luchd-èisteachd Beurla, cleachd an ceangal eadar-theangachaidh: Sergey Larin.
Source: www.habr.com
