I have a buggy function in a shared library. It enters infinite loop when recv() returns 0.
There's no source code. I was able to decompile the buggy part and change some processor instructions without resizing the function, but there's no room for a full fix.
I want to compile the new version with gcc and put it back into the library. The function uses some global and, what's worse, static variables. The fixed function is bigger than the original one, so it can't be put into the same place.
Here it is:
#include <sys/types.h>
#include <stdio.h>
#define PM_ERROR_INVALID_CLIENT 210
typedef struct
{
int code;
int detail_code;
char* message;
} pm_error;
typedef struct
{
char *server_name;
int port;
int socket_descriptor;
int status;
int timeout;
} pm_client;
extern int debug;
int pmprotocol_read(pm_client *param0_client, char *param1_data, int param2_length, pm_error *param3_error)
{
size_t local_bytes_received;
size_t local_total_bytes;
int local_status;
char local_message[128];
int local_retval;
// init globals pointer
// copy params to stack
// pmprotocol.c:896
if (debug > 0)
{
fprintf(
stderr
,"pmprotocol_read:enter\n"
);
}
// pmprotocol.c:897
// pmprotocol.c:898
local_retval = 0;
// pmprotocol.c:900
local_status = 0;
// pmprotocol.c:901
// pmprotocol.c:902
if (param0_client->status != 0)
{
// pmprotocol.c:904
pm_error_set_internal(
param3_error
,"pmprotocol_read"
,"function called with invalid client"
,PM_ERROR_INVALID_CLIENT
);
// pmprotocol.c:905
return 1;
}
// pmprotocol.c:908
local_retval = pmprotocol_waitfor_read(param0_client, param3_error);
// pmprotocol.c:909
if (local_retval != 0)
{
return local_retval;
}
// pmprotocol.c:910
// pmprotocol.c:911
local_total_bytes = 0;
//pmprotocol.c:913
while ((size_t)param2_length > local_total_bytes)
{
//pmprotocol.c:915
local_bytes_received = recv(
param0_client->socket_descriptor
,param1_data + local_total_bytes
,param2_length - local_total_bytes
,0
);
//pmprotocol.c:924
local_total_bytes += local_bytes_received;
}
//pmprotocol.c:928
if (debug > 1)
pmutil_dump_buf(param1_data, param2_length, stderr, "From wire");
//pmprotocol.c:929
if (debug > 0)
fprintf(
stderr
,"pmprotocol_read:finish\n"
);
//pmprotocol.c:930
return local_status;
}
The disassembly:
.skip 0x697c
! typedef long long longlong_t;
! #include "../include/pmtypes.h"
! #include "../include/pmclient.h"
! extern int debug;
global_debug = 0x17c
global__iob = 0x2ac
global_LLC54 = 0x168 ! // "pmprotocol_read:enter\n"
global_LLC56 = 0x170 ! // "From wire"
global_LLC57 = 0x174 ! // "pmprotocol_read:finish\n"
global_LLC55 = 0x16c ! // "pmprotocol_read"
global_LLC38 = 0x128 ! // "function called with invalid client"
.type pmprotocol_read , STT_FUNC
.global pmprotocol_read
.align 4
! int pmprotocol_read(pm_client *param0_client, char *param1_data, int param2_length, pm_error *param3_error)
pmprotocol_read:
pmutil_dump_buf_plt = pmprotocol_read+81856
recv_plt = pmprotocol_read+83308
fprintf_plt = pmprotocol_read+81724
pm_error_set_internal_plt = pmprotocol_read+81868
pmprotocol_waitfor_read_plt = pmprotocol_read+82360
globals = 0x13f70
param0_client = 0x44
param1_data = 0x48
param2_length = 0x4c
param3_error = 0x50
! {
auto_retval = -168
! size_t local_bytes_received;
local_bytes_received = -164
! size_t local_total_bytes;
local_total_bytes = -160
! int local_status;
local_status = -156
! char local_message[128];
local_message = -152
! int local_retval;
local_retval = -20
! // init globals pointer
0xff38691c <+0>: save %sp, -264, %sp
0xff386920 <+4>: sethi %hi(globals), %l7
0xff386924 <+8>: call .-9152
0xff386928 <+12>: add %l7, %lo(globals), %l7
! now %l7==0x13be8
! "No function contains program counter for selected frame."
! now %l7==0xff39a50c
! // copy params to stack
0xff38692c <+16>: st %i0, [ %fp + param0_client ]
0xff386930 <+20>: st %i1, [ %fp + param1_data ]
0xff386934 <+24>: st %i2, [ %fp + param2_length ]
0xff386938 <+28>: st %i3, [ %fp + param3_error ]
! // pmprotocol.c:896
! if (debug > 0)
0xff38693c <+32>: sethi %hi(0), %g1
0xff386940 <+36>: or %g1, global_debug, %g1 ! global_debug
0xff386944 <+40>: ld [ %l7 + %g1 ], %g1 ! (%l7 + %g1)==0xff39a688
! now %g1==0xff39ad54
0xff386948 <+44>: ld [ %g1 ], %g1
0xff38694c <+48>: cmp %g1, 0
0xff386950 <+52>: ble .+48 ! <pmprotocol_read+100>
0xff386954 <+56>: nop
! {
! fprintf(
! stderr
0xff386958 <+60>: sethi %hi(0), %g1
0xff38695c <+64>: or %g1, global__iob, %g1 ! global__iob
0xff386960 <+68>: ld [ %l7 + %g1 ], %g1
0xff386964 <+72>: add %g1, 0x20, %o0
! ,"pmprotocol_read:enter\n"
0xff386968 <+76>: sethi %hi(0), %g1
0xff38696c <+80>: or %g1, global_LLC54, %g1 ! global_LLC54
0xff386970 <+84>: ld [ %l7 + %g1 ], %g1
0xff386974 <+88>: mov %g1, %o1
! );
0xff386978 <+92>: call fprintf_plt
0xff38697c <+96>: nop
! }
! // pmprotocol.c:897
! // pmprotocol.c:898
! local_retval = 0;
0xff386980 <+100>: clr [ %fp + local_retval ]
! // pmprotocol.c:900
! local_status = 0;
0xff386984 <+104>: clr [ %fp + local_status ]
! // pmprotocol.c:901
! // pmprotocol.c:902
! if (param0_client->status != 0)
0xff386988 <+108>: ld [ %fp + param0_client ], %g1
0xff38698c <+112>: ld [ %g1 + 0xc ], %g1
0xff386990 <+116>: cmp %g1, 0
0xff386994 <+120>: be .+72 ! <pmprotocol_read+192>
0xff386998 <+124>: nop
! {
! // pmprotocol.c:904
! pm_error_set_internal(
! param3_error
0xff38699c <+128>: ld [ %fp + param3_error ], %o0
! ,"pmprotocol_read"
0xff3869a0 <+132>: sethi %hi(0), %g1
0xff3869a4 <+136>: or %g1, global_LLC55, %g1 ! global_LLC55
0xff3869a8 <+140>: ld [ %l7 + %g1 ], %g1
0xff3869ac <+144>: mov %g1, %o1
! ,"function called with invalid client"
0xff3869b0 <+148>: sethi %hi(0), %g1
0xff3869b4 <+152>: or %g1, global_LLC38, %g1 ! global_LLC38
0xff3869b8 <+156>: ld [ %l7 + %g1 ], %g1
0xff3869bc <+160>: mov %g1, %o2
! ,PM_ERROR_INVALID_CLIENT
0xff3869c0 <+164>: mov 0xd2, %o3
! );
0xff3869c4 <+168>: call pm_error_set_internal_plt
0xff3869c8 <+172>: nop
! // pmprotocol.c:905
! return 1;
0xff3869cc <+176>: mov 1, %g1 ! 0x1
0xff3869d0 <+180>: st %g1, [ %fp + auto_retval ]
0xff3869d4 <+184>: b .+320 ! <pmprotocol_read+504>
0xff3869d8 <+188>: nop
! }
! // pmprotocol.c:908
! local_retval = pmprotocol_waitfor_read(param0_client, param3_error);
0xff3869dc <+192>: ld [ %fp + param0_client ], %o0
0xff3869e0 <+196>: ld [ %fp + param3_error ], %o1
0xff3869e4 <+200>: call pmprotocol_waitfor_read_plt
0xff3869e8 <+204>: nop
0xff3869ec <+208>: mov %o0, %g1
0xff3869f0 <+212>: st %g1, [ %fp + local_retval ]
! // pmprotocol.c:909
! if (local_retval != 0)
0xff3869f4 <+216>: ld [ %fp + local_retval ], %g1
0xff3869f8 <+220>: cmp %g1, 0
0xff3869fc <+224>: be .+24 ! <pmprotocol_read+248>
0xff386a00 <+228>: nop
! {
! return local_retval;
0xff386a04 <+232>: ld [ %fp + local_retval ], %g1
0xff386a08 <+236>: st %g1, [ %fp + auto_retval ]
0xff386a0c <+240>: b .+264 ! <pmprotocol_read+504>
0xff386a10 <+244>: nop
! }
! // pmprotocol.c:910
! // pmprotocol.c:911
! local_total_bytes = 0;
0xff386a14 <+248>: clr [ %fp + local_total_bytes ]
! //pmprotocol.c:913
! while ((size_t)param2_length > local_total_bytes)
0xff386a18 <+252>: ld [ %fp + param2_length ], %o5
0xff386a1c <+256>: ld [ %fp + local_total_bytes ], %g1
0xff386a20 <+260>: cmp %o5, %g1
0xff386a24 <+264>: bleu .+88 ! <pmprotocol_read+352>
0xff386a28 <+268>: nop
! {
! //pmprotocol.c:915
! local_bytes_received = recv(
0xff386a2c <+272>: ld [ %fp + param0_client ], %o3
0xff386a30 <+276>: ld [ %fp + param1_data ], %o5
0xff386a34 <+280>: ld [ %fp + local_total_bytes ], %g1
0xff386a38 <+284>: add %o5, %g1, %o4
0xff386a3c <+288>: ld [ %fp + param2_length ], %o5
0xff386a40 <+292>: ld [ %fp + local_total_bytes ], %g1
0xff386a44 <+296>: sub %o5, %g1, %g1
! param0_client->socket_descriptor
0xff386a48 <+300>: ld [ %o3 + 8 ], %o0
! ,param1_data + local_total_bytes
0xff386a4c <+304>: mov %o4, %o1
! ,param2_length - local_total_bytes
0xff386a50 <+308>: mov %g1, %o2
! ,0
0xff386a54 <+312>: clr %o3
! );
0xff386a58 <+316>: call recv_plt
0xff386a5c <+320>: nop
0xff386a60 <+324>: st %o0, [ %fp + local_bytes_received ]
! //pmprotocol.c:924
! local_total_bytes += local_bytes_received;
0xff386a64 <+328>: ld [ %fp + local_total_bytes ], %o5
0xff386a68 <+332>: ld [ %fp + local_bytes_received ], %g1
0xff386a6c <+336>: add %o5, %g1, %g1
0xff386a70 <+340>: st %g1, [ %fp + local_total_bytes ]
! }
0xff386a74 <+344>: b .-92 ! <pmprotocol_read+252>
0xff386a78 <+348>: nop
! //pmprotocol.c:928
! if (debug > 1)
0xff386a7c <+352>: sethi %hi(0), %g1
0xff386a80 <+356>: or %g1, global_debug, %g1 ! global_debug
0xff386a84 <+360>: ld [ %l7 + %g1 ], %g1
0xff386a88 <+364>: ld [ %g1 ], %g1
0xff386a8c <+368>: cmp %g1, 1
0xff386a90 <+372>: ble .+56 ! <pmprotocol_read+428>
0xff386a94 <+376>: nop
! pmutil_dump_buf(param1_data, param2_length, stderr, "From wire");
0xff386a98 <+380>: ld [ %fp + param1_data ], %o0
0xff386a9c <+384>: ld [ %fp + param2_length ], %o1
0xff386aa0 <+388>: sethi %hi(0), %g1
0xff386aa4 <+392>: or %g1, global__iob, %g1 ! global__iob
0xff386aa8 <+396>: ld [ %l7 + %g1 ], %g1
0xff386aac <+400>: add %g1, 0x20, %o2
0xff386ab0 <+404>: sethi %hi(0), %g1
0xff386ab4 <+408>: or %g1, global_LLC56, %g1 ! global_LLC56
0xff386ab8 <+412>: ld [ %l7 + %g1 ], %g1
0xff386abc <+416>: mov %g1, %o3
0xff386ac0 <+420>: call pmutil_dump_buf_plt
0xff386ac4 <+424>: nop
! //pmprotocol.c:929
! if (debug > 0)
0xff386ac8 <+428>: sethi %hi(0), %g1
0xff386acc <+432>: or %g1, global_debug, %g1 ! global_debug
0xff386ad0 <+436>: ld [ %l7 + %g1 ], %g1
0xff386ad4 <+440>: ld [ %g1 ], %g1
0xff386ad8 <+444>: cmp %g1, 0
0xff386adc <+448>: ble .+48 ! <pmprotocol_read+496>
0xff386ae0 <+452>: nop
! fprintf(
! stderr
0xff386ae4 <+456>: sethi %hi(0), %g1
0xff386ae8 <+460>: or %g1, global__iob, %g1 ! global__iob
0xff386aec <+464>: ld [ %l7 + %g1 ], %g1
0xff386af0 <+468>: add %g1, 0x20, %o0
! ,"pmprotocol_read:finish\n"
0xff386af4 <+472>: sethi %hi(0), %g1
0xff386af8 <+476>: or %g1, global_LLC57, %g1 ! global_LLC57
0xff386afc <+480>: ld [ %l7 + %g1 ], %g1
0xff386b00 <+484>: mov %g1, %o1
! );
0xff386b04 <+488>: call fprintf_plt
0xff386b08 <+492>: nop
! //pmprotocol.c:930
! return local_status;
0xff386b0c <+496>: ld [ %fp + local_status ], %g1
0xff386b10 <+500>: st %g1, [ %fp + auto_retval ]
0xff386b14 <+504>: ld [ %fp + auto_retval ], %i0
0xff386b18 <+508>: ret
0xff386b1c <+512>: restore
! }