PVS-સ્ટુડિયો વિશ્લેષકનો ઉપયોગ કરીને rdesktop અને xrdp તપાસી રહ્યું છે

PVS-સ્ટુડિયો વિશ્લેષકનો ઉપયોગ કરીને rdesktop અને xrdp તપાસી રહ્યાં છીએ
RDP પ્રોટોકોલ સાથે કામ કરવા માટે ઓપન સોર્સ પ્રોગ્રામ્સનું પરીક્ષણ કરવા વિશેના લેખોની શ્રેણીમાં આ બીજી સમીક્ષા છે. તેમાં આપણે rdesktop ક્લાયન્ટ અને xrdp સર્વરને જોઈશું.

ભૂલોને ઓળખવા માટેના સાધન તરીકે ઉપયોગ થાય છે પીવીએસ-સ્ટુડિયો. તે C, C++, C# અને Java ભાષાઓ માટે સ્ટેટિક કોડ વિશ્લેષક છે, જે Windows, Linux અને macOS પ્લેટફોર્મ પર ઉપલબ્ધ છે.

લેખ ફક્ત તે ભૂલો રજૂ કરે છે જે મને રસપ્રદ લાગતી હતી. જો કે, પ્રોજેક્ટ નાના છે, તેથી થોડી ભૂલો હતી :).

નોંધણી. ફ્રીઆરડીપી પ્રોજેક્ટ વેરિફિકેશન વિશે અગાઉનો લેખ મળી શકે છે અહીં.

rdesktop

rdesktop — UNIX-આધારિત સિસ્ટમો માટે RDP ક્લાયંટનું મફત અમલીકરણ. જો તમે સિગ્વિન હેઠળ પ્રોજેક્ટ બનાવો છો તો તેનો ઉપયોગ વિન્ડોઝ હેઠળ પણ થઈ શકે છે. GPLv3 હેઠળ લાઇસન્સ.

આ ક્લાયંટ ખૂબ જ લોકપ્રિય છે - તે ReactOS માં ડિફૉલ્ટ રૂપે ઉપયોગમાં લેવાય છે, અને તમે તેના માટે તૃતીય-પક્ષ ગ્રાફિકલ ફ્રન્ટ-એન્ડ્સ પણ શોધી શકો છો. જો કે, તે ખૂબ વૃદ્ધ છે: તેની પ્રથમ રજૂઆત 4 એપ્રિલ, 2001 ના રોજ થઈ હતી - લેખન સમયે, તે 17 વર્ષનો છે.

મેં અગાઉ નોંધ્યું છે તેમ, પ્રોજેક્ટ તદ્દન નાનો છે. તેમાં કોડની લગભગ 30 હજાર લાઇન છે, જે તેની ઉંમરને ધ્યાનમાં રાખીને થોડી વિચિત્ર છે. સરખામણી માટે, ફ્રીઆરડીપીમાં 320 હજાર રેખાઓ છે. અહીં ક્લોક પ્રોગ્રામનું આઉટપુટ છે:

PVS-સ્ટુડિયો વિશ્લેષકનો ઉપયોગ કરીને rdesktop અને xrdp તપાસી રહ્યાં છીએ

અગમ્ય કોડ

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 નો ઉપયોગ કરવો

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 ને અનુરૂપ છે જો આપણે ચલ વિશે વાત કરી રહ્યા છીએ ઘરનાં પરચૂરણ કામો. તે તારણ આપે છે કે પ્રતીક 0xFF, જેમ EOF (-1) ફાઇલના અંત તરીકે અર્થઘટન કરવામાં આવે છે. આવી ભૂલોને ટાળવા માટે, કાર્યનું પરિણામ છે fgetc જેવા ચલમાં સંગ્રહિત હોવું જોઈએ પૂર્ણાંક.

ટાઈપો

ટુકડો 1

V547 અભિવ્યક્તિ 'write_time' હંમેશા ખોટી હોય છે. 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 ની બરાબર છે: આ કિસ્સામાં આપણે એક શાખામાં સમાપ્ત થઈશું બીજું: ચલ મોડ_સમય અનુગામી સ્થિતિને ધ્યાનમાં લીધા વિના હંમેશા 0 રહેશે.
  • ચલોમાંનું એક 0 છે: મોડ_સમય 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' ફંક્શનનો કૉલ બફર 'ફુલપાથ'ના ઓવરફ્લો તરફ દોરી જશે. 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 શરતી અભિવ્યક્તિનો એક ભાગ હંમેશા સાચો હોય છે: ઉમેરો > 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 - ઓપન સોર્સ કોડ સાથે આરડીપી સર્વરનું અમલીકરણ. પ્રોજેક્ટને 2 ભાગોમાં વહેંચવામાં આવ્યો છે:

  • xrdp - પ્રોટોકોલ અમલીકરણ. Apache 2.0 લાયસન્સ હેઠળ વિતરિત.
  • xorgxrdp - xrdp સાથે વાપરવા માટે Xorg ડ્રાઇવરોનો સમૂહ. લાઇસન્સ - X11 (જેમ કે MIT, પરંતુ જાહેરાતમાં ઉપયોગને પ્રતિબંધિત કરે છે)

પ્રોજેક્ટનો વિકાસ rdesktop અને FreeRDP ના પરિણામો પર આધારિત છે. શરૂઆતમાં, ગ્રાફિક્સ સાથે કામ કરવા માટે, તમારે અલગ VNC સર્વર, અથવા RDP સપોર્ટ - X11rdp સાથે વિશિષ્ટ X11 સર્વરનો ઉપયોગ કરવો પડ્યો, પરંતુ xorgxrdp ના આગમન સાથે, તેમની જરૂરિયાત અદૃશ્ય થઈ ગઈ.

આ લેખમાં અમે xorgxrdpને આવરીશું નહીં.

xrdp પ્રોજેક્ટ, અગાઉના પ્રોજેક્ટની જેમ, ખૂબ જ નાનો છે અને તેમાં લગભગ 80 હજાર લાઈનો છે.

PVS-સ્ટુડિયો વિશ્લેષકનો ઉપયોગ કરીને rdesktop અને xrdp તપાસી રહ્યાં છીએ

વધુ ટાઈપો

V525 કોડમાં સમાન બ્લોક્સનો સંગ્રહ છે. 87, 88, 89 પંક્તિઓમાં 'r', 'g', 'r' વસ્તુઓ તપાસો. 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 લાઇબ્રેરીમાંથી લેવામાં આવ્યો હતો, જે RemoteFX માટે jpeg2000 કોડેકનો અમલ કરે છે. અહીં, દેખીતી રીતે, ગ્રાફિક ડેટા ચેનલો મિશ્રિત છે - "વાદળી" રંગને બદલે, "લાલ" રેકોર્ડ કરવામાં આવે છે. આ ભૂલ મોટા ભાગે કોપી-પેસ્ટના પરિણામે દેખાઈ છે.

સમાન કાર્યમાં સમાન સમસ્યા આવી rfx_encode_format_argb, જે વિશ્લેષકે અમને પણ કહ્યું:

V525 કોડમાં સમાન બ્લોક્સનો સંગ્રહ છે. 260, 261, 262, 263 લાઇનમાં આઇટમ્સ 'a', 'r', 'g', 'r' તપાસો. 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))
  {
    ....
  }
  ....
}

ફંક્શન એક પ્રકારનું ચલ વાંચે છે ટૂંકમાં સહી વિનાનું જેવા ચલ માં પૂર્ણાંક. અહીં તપાસ કરવાની જરૂર નથી કારણ કે આપણે સહી ન કરેલ વેરીએબલ વાંચીએ છીએ અને પરિણામ મોટા વેરીએબલને સોંપી રહ્યા છીએ, તેથી વેરીએબલ નકારાત્મક મૂલ્ય લઈ શકતું નથી.

બિનજરૂરી તપાસ

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 નું ટ્રાયલ વર્ઝન ડાઉનલોડ કરી શકો છો સાઇટ.

PVS-સ્ટુડિયો વિશ્લેષકનો ઉપયોગ કરીને rdesktop અને xrdp તપાસી રહ્યાં છીએ

જો તમે આ લેખ અંગ્રેજી બોલતા પ્રેક્ષકો સાથે શેર કરવા માંગતા હો, તો કૃપા કરીને અનુવાદ લિંકનો ઉપયોગ કરો: Sergey Larin. PVS-Studio સાથે rdesktop અને xrdp તપાસી રહ્યાં છીએ

સોર્સ: www.habr.com

એક ટિપ્પણી ઉમેરો