Ticket #1155: segfault-when-network_opers_parse.patch

File segfault-when-network_opers_parse.patch, 3.4 KB (added by sean_chiang@…, 5 years ago)

refactoring the network_opers_parse() to solve segfault issue

  • src/gsmd/usock.c

    === src/gsmd/usock.c
    ==================================================================
     
    767767        return ret; 
    768768} 
    769769 
    770 static int network_opers_parse(const char *str, struct gsmd_msg_oper out[]) 
     770static int network_opers_parse(const char *str, struct gsmd_msg_oper **out) 
    771771{ 
    772772        int len = 0; 
    773         int stat, n; 
    774         char opname_longalpha[16 + 1]; 
    775         char opname_shortalpha[8 + 1]; 
    776         char opname_num[6 + 1]; 
     773        struct gsm_extrsp *er; 
     774        char buf[64]; 
     775        char *head, *tail, *ptr; 
     776        struct gsmd_msg_oper *out2; 
    777777 
    778778        if (strncmp(str, "+COPS: ", 7)) 
    779                 goto final; 
    780         str += 7; 
     779                return -EINVAL; 
    781780 
    782         while (*str == '(') { 
    783                 if (out) { 
    784                         out->is_last = 0; 
    785                         if (sscanf(str, 
    786                                                 "(%i,\"%16[^\"]\"," 
    787                                                 "\"%8[^\"]\",\"%6[0-9]\")%n", 
    788                                                 &stat, 
    789                                                 opname_longalpha, 
    790                                                 opname_shortalpha, 
    791                                                 opname_num, 
    792                                                 &n) < 4) 
    793                                 goto final; 
    794                         out->stat = stat; 
    795                         memcpy(out->opname_longalpha, opname_longalpha, 
    796                                         sizeof(out->opname_longalpha)); 
    797                         memcpy(out->opname_shortalpha, opname_shortalpha, 
    798                                         sizeof(out->opname_shortalpha)); 
    799                         memcpy(out->opname_num, opname_num, 
    800                                         sizeof(out->opname_num)); 
    801                 } else 
    802                         if (sscanf(str, 
    803                                                 "(%*i,\"%*[^\"]\"," 
    804                                                 "\"%*[^\"]\",\"%*[0-9]\")%n", 
    805                                                 &n) < 0) 
    806                                 goto final; 
    807                 if (n < 10 || str[n - 1] != ')') 
    808                         goto final; 
    809                 if (str[n] == ',') 
    810                         n ++; 
    811                 str += n; 
    812                 len ++; 
    813                 if (out) 
    814                         out ++; 
     781        ptr = str; 
     782        while (*str) { 
     783                if ( *str == '(' && isdigit(*(str+1)) ) { 
     784                        len++;   
     785                        str+=2; 
     786                } 
     787                else 
     788                        str++; 
    815789        } 
    816 final: 
    817         if (out) 
    818                 out->is_last = 1; 
     790 
     791        *out = talloc_size(__gu_ctx, sizeof(struct gsmd_msg_oper) * (len + 1)); 
     792 
     793        if (!out) 
     794                return -ENOMEM; 
     795 
     796        out2 = *out; 
     797        str = ptr; 
     798 
     799        while (*str) { 
     800                if ( *str == '(' ) 
     801                        head = str; 
     802                else if ( *str == ')' ) { 
     803                        tail = str; 
     804                         
     805                        memset(buf, '\0', sizeof(buf)); 
     806                        strncpy(buf, head+1, (tail-head-1)); 
     807 
     808                        DEBUGP("buf: %s\n", buf); 
     809 
     810                        er = extrsp_parse(gsmd_tallocs, buf); 
     811 
     812                        if ( !er ) 
     813                                return -ENOMEM; 
     814 
     815                        //extrsp_dump(er);       
     816                                 
     817                        if ( er->num_tokens == 4 && 
     818                                        er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC && 
     819                                        er->tokens[1].type == GSMD_ECMD_RTT_STRING && 
     820                                        er->tokens[2].type == GSMD_ECMD_RTT_STRING && 
     821                                        er->tokens[3].type == GSMD_ECMD_RTT_STRING ) { 
     822                                 
     823                                /* 
     824                                 * +COPS=? +COPS: [list of supported (<stat>,long alphanumeric <oper> 
     825                                 *       ,short alphanumeric <oper>,numeric <oper>)s] 
     826                                 */ 
     827                                 
     828                                out2->stat = er->tokens[0].u.numeric; 
     829                                strcpy(out2->opname_longalpha, er->tokens[1].u.string); 
     830                                strcpy(out2->opname_shortalpha, er->tokens[2].u.string); 
     831                                strcpy(out2->opname_num, er->tokens[3].u.string); 
     832                        } 
     833                        else { 
     834                                DEBUGP("Invalid Input : Parse error\n"); 
     835                                talloc_free(*out); 
     836                                return -EINVAL; 
     837                        } 
     838 
     839                        talloc_free(er); 
     840 
     841                        out2 ++; 
     842                } 
     843 
     844                str ++; 
     845        } 
     846 
     847        out2->is_last = 1; 
    819848        return len; 
    820849} 
    821850 
    822851static int network_opers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) 
    823852{ 
    824853        struct gsmd_user *gu = ctx; 
    825         struct gsmd_msg_oper *buf; 
     854        struct gsmd_msg_oper *buf = NULL; 
    826855        int len, ret; 
    827856 
    828         len = network_opers_parse(resp, 0); 
    829         buf = talloc_size(__gu_ctx, sizeof(struct gsmd_msg_oper) * (len + 1)); 
    830         if (!buf) 
    831                 return -ENOMEM; 
    832         network_opers_parse(resp, buf); 
     857        len = network_opers_parse(resp, &buf); 
    833858 
    834859        ret = gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_OPER_LIST, 
    835860                        cmd->id, sizeof(*buf) * (len + 1), buf);