Iki minangka review kapindho ing seri artikel babagan nguji program open source kanggo nggarap protokol RDP. Ing kita bakal katon ing klien rdesktop lan server xrdp.
Digunakake minangka alat kanggo ngenali kesalahan
Artikel kasebut mung nuduhake kesalahan sing katon menarik kanggo aku. Nanging, proyek kasebut cilik, mula ana sawetara kesalahan :).
komentar. Artikel sadurunge babagan verifikasi proyek FreeRDP bisa ditemokake
rdesktop
Klien iki populer banget - digunakake minangka standar ing ReactOS, lan sampeyan uga bisa nemokake ngarep grafis pihak katelu. Nanging, dheweke wis cukup tuwa: release pisanan ing April 4, 2001 - ing wektu nulis, iku 17 taun.
Kaya sing dakkandhakake sadurunge, proyek kasebut cilik banget. Isine kira-kira 30 ewu baris kode, sing rada aneh amarga umure. Kanggo mbandhingake, FreeRDP ngemot 320 ewu baris. Iki minangka output saka program Cloc:
Kode sing ora bisa digayuh
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);
}
Kesalahan ketemu kita langsung ing fungsi utama: kita ndeleng kode teka sawise operator bali - pecahan iki nindakake reresik memori. Nanging, kesalahan ora nyebabake ancaman: kabeh memori sing diparengake bakal dibusak dening sistem operasi sawise program metu.
Ora ana kesalahan penanganan
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);
}
....
}
Potongan kode ing kasus iki diwaca saka file menyang buffer nganti file rampung. Nanging, ora ana kesalahan nangani ing kene: yen ana sing salah, banjur maca bakal bali -1, lan banjur Uploaded bakal overrun Output.
Nggunakake EOF ing jinis char
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++;
}
....
}
Ing kene kita ndeleng penanganan sing salah kanggo nggayuh pungkasan file: yen fgetc ngasilake karakter sing kode 0xFF, bakal diinterpretasikake minangka pungkasan file (EOF).
EOF iku pancet, biasane ditetepake minangka -1. Contone, ing enkoding CP1251, huruf pungkasan alfabet Rusia duwe kode 0xFF, sing cocog karo nomer -1 yen kita ngomong babagan variabel kaya char. Pranyata metu sing simbol 0xFF, kaya EOF (-1) diinterpretasikake minangka pungkasan file. Kanggo ngindhari kesalahan kasebut, asil saka fungsi kasebut fgetc kudu disimpen ing variabel kaya int.
Salah ketik
Fragmen 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; // <=
....
}
Mungkin penulis kode iki salah || ΠΈ && ing kahanan. Ayo nimbang opsi sing bisa ditrapake kanggo nilai nulis_wektu ΠΈ ganti_wektu:
- Loro-lorone variabel padha karo 0: ing kasus iki kita bakal mungkasi ing cabang liya: variabel wektu_mod bakal tansah 0 preduli saka kondisi sakteruse.
- Salah sawijining variabel yaiku 0: wektu_mod bakal padha karo 0 (yen variabel liyane nduweni nilai non-negatif), amarga MIN bakal milih sing luwih cilik saka rong pilihan.
- Loro-lorone variabel ora padha karo 0: pilih nilai minimal.
Nalika ngganti kondisi karo write_time && change_time prilaku bakal katon bener:
- Siji utawa loro variabel ora padha karo 0: pilih nilai non-nol.
- Loro-lorone variabel ora padha karo 0: pilih nilai minimal.
Fragmen 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;
....
}
Pranyata operator uga campur ing kene || ΠΈ &&, utawa == ΠΈ !=: Variabel ora bisa duwe nilai 20 lan 9 ing wektu sing padha.
Nyalin baris tanpa wates
RD_NTSTATUS
disk_query_directory(....)
{
....
char *dirname, fullpath[PATH_MAX];
....
/* Get information for directory entry */
sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
....
}
Nalika katon ing fungsi lengkap, bakal dadi cetha yen kode iki ora nimbulakΓ© masalah. Nanging, bisa uga ana ing mangsa ngarep: siji owah-owahan sing sembrono lan kita bakal entuk kebanjiran buffer - sprint ora winates dening apa, supaya nalika concatenating path kita bisa ngluwihi wates saka Uploaded. Disaranake kanggo sok dong mirsani telpon iki ing snprintf(fullpath, PATH_MAX, β¦.).
Kondisi keluwih
static void
inRepos(STREAM in, unsigned int read)
{
SERVER_DWORD add = 4 - read % 4;
if (add < 4 && add > 0)
{
....
}
}
pengawasan tambah > 0 ana ora perlu kene: variabel bakal tansah luwih saka nul, amarga maca% 4 bakal ngasilake sisa bagean, nanging ora bakal padha karo 4.
xrdp
- xrdp - implementasi protokol. Didistribusikake miturut lisensi Apache 2.0.
- xorgxrdp - A set driver Xorg kanggo nggunakake xrdp. Lisensi - X11 (kaya MIT, nanging nglarang panggunaan ing pariwara)
Pangembangan proyek kasebut adhedhasar asil rdesktop lan FreeRDP. Kaping pisanan, kanggo nggarap grafis, sampeyan kudu nggunakake server VNC sing kapisah, utawa server X11 khusus kanthi dhukungan RDP - X11rdp, nanging kanthi kedadeyan xorgxrdp, kabutuhan kasebut ilang.
Ing artikel iki kita ora bakal nutupi xorgxrdp.
Proyek xrdp, kaya sing sadurunge, cilik banget lan ngemot kira-kira 80 ewu baris.
Typo liyane
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++;
}
....
}
....
}
Kode iki dijupuk saka perpustakaan librfxcodec, sing ngleksanakake codec jpeg2000 kanggo RemoteFX. Ing kene, ketoke, saluran data grafis dicampur - tinimbang warna "biru", "abang" direkam. Kesalahan iki umume muncul amarga nyalin-tempel.
Masalah sing padha dumadi ing fungsi sing padha rfx_encode_format_argb, sing analisa uga ngandhani:
while (x < 64)
{
*la_buf++ = a;
*lr_buf++ = r;
*lg_buf++ = g;
*lb_buf++ = r;
x++;
}
Deklarasi 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];
....
}
....
}
Pranyatan lan definisi Uploaded ing loro file iki ora kompatibel - ukuran beda-beda 1. Nanging, ora ana kasalahan - ukuran bener kasebut ing file evdev-map.c, supaya ora ana metu saka wates. Dadi iki mung bug sing bisa didandani kanthi gampang.
Bandhingan sing salah
// 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))
{
....
}
....
}
Fungsi kasebut maca variabel jinis unsigned cendhak dadi variabel kaya int. Priksa ora dibutuhake ing kene amarga kita maca variabel sing ora ditandatangani lan menehi asil menyang variabel sing luwih gedhe, mula variabel kasebut ora bisa njupuk nilai negatif.
Priksa sing ora perlu
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;
}
....
}
Priksa ketimpangan ora ana gunane amarga kita wis duwe perbandingan ing wiwitan. Kemungkinan iki salah ketik lan pangembang pengin nggunakake operator kasebut || kanggo nyaring argumen sing ora sah.
kesimpulan
Sajrone audit, ora ana kesalahan serius sing diidentifikasi, nanging akeh kekurangan sing ditemokake. Nanging, desain kasebut digunakake ing pirang-pirang sistem, sanajan ukurane cilik. Proyek cilik ora kudu akeh kesalahan, mula sampeyan ora kudu ngadili kinerja penganalisa mung ing proyek cilik. Sampeyan bisa maca liyane babagan iki ing artikel "
Sampeyan bisa ngundhuh versi nyoba PVS-Studio saka kita
Yen sampeyan pengin nuduhake artikel iki karo pamirsa sing nganggo basa Inggris, gunakake tautan terjemahan: Sergey Larin.
Source: www.habr.com