Ev nirxandina duyemîn e di rêze gotaran de li ser ceribandina bernameyên çavkaniya vekirî ji bo xebata bi protokola RDP re. Di wê de em ê li muwekîlê rdesktop û servera xrdp binêrin.
Ji bo tespîtkirina xeletiyan wekî amûrek tê bikar anîn
Gotar tenê wan xeletiyên ku ji min re balkêş xuya bûn pêşkêşî dike. Lêbelê, proje piçûk in, ji ber vê yekê kêm xeletî hebûn :).
bingotin. Gotarek berê di derbarê verastkirina projeya FreeRDP de dikare were dîtin
rdesktop
Ev xerîdar pir populer e - ew ji hêla xwerû ve di ReactOS-ê de tê bikar anîn, û hûn dikarin ji bo wê pêşiyên grafîkî yên sêyemîn jî bibînin. Lêbelê, ew pir pîr e: serbestberdana wî ya yekem di 4ê Avrêl, 2001 de pêk hat - di dema nivîsandinê de, ew 17 salî ye.
Wekî ku min berê jî diyar kir, proje pir piçûk e. Nêzîkî 30 hezar rêzikên kodê dihewîne, ku ji ber temenê wê hinekî ecêb e. Ji bo berhevdanê, FreeRDP 320 hezar rêzan dihewîne. Li vir encama bernameya Clocê ye:
Koda ku nayê gihîştin
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);
}
Çewtî yekser di fonksiyonê de rastî me tê dest: em dibînin ku koda piştî operatorê tê vegera - ev perçe paqijkirina bîranînê dike. Lêbelê, xeletî tehdîd nake: hemî bîranîna veqetandî dê piştî ku bername derkeve ji hêla pergala xebitandinê ve were paqij kirin.
Desthilatdariya xeletiyê tune
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);
}
....
}
Di vê rewşê de pişka kodê ji pelê di nav tamponek de dixwîne heya ku pel biqede. Lêbelê, li vir guheztina xeletiyek tune: heke tiştek xelet derkeve, wê hingê xwendin dê vegere -1, û dûv re array dê biqede karûabr.
Bikaranîna EOF di celebê char de
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++;
}
....
}
Li vir em destwerdana nerast a gihîştina dawiya pelê dibînin: eger fgetc Karaktera ku koda wê 0xFF ye vedigerîne, ew ê wekî dawiya pelê were şîrove kirin (EOF).
EOF ew domdar e, bi gelemperî wekî -1 tê pênase kirin. Mînakî, di şîfrekirina CP1251 de, tîpa paşîn a alfabeya rûsî koda 0xFF heye, ku bi hejmara -1 re têkildar e heke em qala guhêrbarek mîna char. Derket holê ku sembola 0xFF, mîna EOF (-1) wekî dawiya pelê tê şîrove kirin. Ji bo ku ji xeletiyên weha dûr nekevin, encama fonksiyonê ye fgetc divê di guhêrbarek mîna de were hilanîn int.
Çewtiya tîpan
Parçeya 1
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; // <=
....
}
Dibe ku nivîskarê vê kodê ew xelet kiriye || и && di rewşê de. Werin em vebijarkên gengaz ên ji bo nirxan bifikirin nivîsandin_dem и change_time:
- Her du guhêrbar jî 0-yê ne: Di vê rewşê de em ê bikevin şaxekê wekîdi: guherbar mod_time dê her dem 0 be bêyî ku şertê paşerojê hebe.
- Yek ji guherbaran 0 ye: mod_time dê bibe 0 (bi şertê ku guhêrbarek din xwedî nirxek ne-neyînî be), ji ber MIN dê ji her du vebijarkên piçûktir hilbijêrin.
- Her du guhêrbar ne wekhev in 0: nirxa herî kêm hilbijêrin.
Dema ku şertê bi şûna dema_nivîsandinê && dema_guhertinê tevger dê rast xuya bike:
- Yek an herdu guhêrbar ne wekhev in 0: nirxek ne-sifir hilbijêrin.
- Her du guhêrbar ne wekhev in 0: nirxa herî kêm hilbijêrin.
Parçeya 2
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;
....
}
Xuya ye operator li vir jî tevlihev bûne || и &&an jî == и !=: Guherbarek nikare di heman demê de nirxa 20 û 9 hebe.
Kopîkirina xeta bêsînor
RD_NTSTATUS
disk_query_directory(....)
{
....
char *dirname, fullpath[PATH_MAX];
....
/* Get information for directory entry */
sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
....
}
Dema ku hûn li fonksiyonê bi tevahî mêze bikin, dê diyar bibe ku ev kod nabe sedema pirsgirêkan. Lêbelê, ew dikarin di pêşerojê de çêbibin: Guhertinek bêhiş û em ê zerarek tampon bistînin - sprint ji hêla tiştek ve ne sînorkirî ye, ji ber vê yekê dema ku riyan bi hev ve girêdidin em dikarin ji sînorên rêzê derbas bibin. Tête pêşniyar kirin ku li ser vê bangê hişyar bikin snprintf (tevahî rê, PATH_MAX,….).
Rewşa zêde
static void
inRepos(STREAM in, unsigned int read)
{
SERVER_DWORD add = 4 - read % 4;
if (add < 4 && add > 0)
{
....
}
}
Kontrola lê zêde bike > 0 li vir ne hewce ye: guhêrbar dê her dem ji sifirê mezintir be, ji ber % 4 bixwînin dê beşa mayî ya dabeşkirinê vegerîne, lê ew ê qet nebe 4.
xrdp
- xrdp - pêkanîna protokolê. Di bin lîsansa Apache 2.0 de belav kirin.
- xorgxrdp - Komek ajokarên Xorg ji bo karanîna bi xrdp. Lîsans - X11 (mîna MIT, lê di reklamê de karanîna qedexe dike)
Pêşveçûna projeyê li ser encamên rdesktop û FreeRDP-ê ye. Di destpêkê de, ji bo ku hûn bi grafîkê re bixebitin, pêdivî bû ku hûn serverek VNC-ya veqetandî, an serverek X11-a taybetî ya bi piştgiriya RDP - X11rdp bikar bînin, lê bi hatina xorgxrdp re, hewcedariya wan winda bû.
Di vê gotarê de em ê xorgxrdp negirin.
Projeya xrdp, wek ya berê, pir piçûk e û bi qasî 80 hezar rêzan tê de ye.
Zêdetir xeletiyên tîpan
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++;
}
....
}
....
}
Ev kod ji pirtûkxaneya librfxcodec, ku kodek jpeg2000 ji bo RemoteFX bicîh tîne, hate girtin. Li vir, xuya ye, kanalên daneya grafîkî tevlihev dibin - li şûna rengê "şîn", "sor" tê tomar kirin. Ev xeletî bi îhtîmaleke mezin di encama kopî-paste de derket.
Heman pirsgirêk di fonksiyonek wekhev de çêbû rfx_encode_format_argb, ku analîzer jî ji me re got:
while (x < 64)
{
*la_buf++ = a;
*lr_buf++ = r;
*lg_buf++ = g;
*lb_buf++ = r;
x++;
}
Daxuyaniya Array
// 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];
....
}
....
}
Di van her du pelan de danasîn û pênaseya rêzê li hev nayên - mezinahî bi 1-ê cûda ye. Lêbelê, xeletiyek çênabe - mezinahiya rast di pelê evdev-map.c de hatî destnîşan kirin, ji ber vê yekê ji sînoran dernakeve. Ji ber vê yekê ev tenê xeletiyek e ku bi hêsanî dikare were rast kirin.
Berawirdkirina çewt
// 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))
{
....
}
....
}
Fonksiyon guhêrbarek tîpek dixwîne bê îmze kurt nav guherbareke wek int. Kontrolkirin li vir ne hewce ye ji ber ku em guhêrbarek nenîşankirî dixwînin û encamê ji guhêrbarek mezintir re destnîşan dikin, ji ber vê yekê guhêrbar nikare nirxek neyînî bigire.
Kontrolên nepêwist
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;
}
....
}
Kontrolên newekheviyê li vir wate nadin ji ber ku di destpêkê de berhevokek me heye. Ihtîmal e ku ev xeletiyek tîpî ye û pêşdebir dixwest ku operator bikar bîne || ji bo fîlterkirina argumanên nederbasdar.
encamê
Di dema kontrolê de xeletiyên cidî nehatin dîtin, lê gelek kêmasî hatin dîtin. Lêbelê, ev sêwiran di gelek pergalan de têne bikar anîn, her çend di çarçoveyek piçûk de bin. Projeyek piçûk ne hewce ye ku gelek xeletî hebe, ji ber vê yekê divê hûn performansa analîzer tenê li ser projeyên piçûk dadbar nekin. Hûn dikarin li ser vê gotarê bêtir bixwînin "
Hûn dikarin guhertoyek ceribandinê ya PVS-Studio ji me dakêşin
Heke hûn dixwazin vê gotarê bi temaşevanên îngilîzîaxêv re parve bikin, ji kerema xwe lînka wergerê bikar bînin: Sergey Larin.
Source: www.habr.com