TSG-7636: 修复读越界问题
This commit is contained in:
@@ -118,6 +118,12 @@ static int get_value(unsigned char *payload, int *offset, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_length(int last_len, int field_len)
|
||||
{
|
||||
return ((last_len-field_len>0) ? 1 : 0);
|
||||
}
|
||||
|
||||
int quic_getLinkState(struct _quic_context *_context)
|
||||
{
|
||||
UCHAR state = 0;
|
||||
@@ -229,23 +235,39 @@ unsigned long long get_variable_length(char *p, int offset, int v_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long bit_to_value(char *payload, unsigned char flags, unsigned long long *out_value, int *used_len)
|
||||
long long bit_to_value(char *payload, int payload_len, unsigned char flags, unsigned long long *out_value, int *used_len)
|
||||
{
|
||||
switch(flags&0x3) // packet number
|
||||
{
|
||||
case 0x3: // 6 bytes
|
||||
if(!check_length(payload_len-*used_len, 6))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*out_value=get_variable_length(payload, *used_len, 6);
|
||||
*used_len+=6;
|
||||
break;
|
||||
case 0x2: // 4 bytes
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned int)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*out_value=(unsigned long long)ntohl(*(unsigned int *)(payload+*used_len));
|
||||
*used_len+=4;
|
||||
break;
|
||||
case 0x1: // 2bytes
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned short)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*out_value=(unsigned long long)ntohs(*(unsigned short *)(payload+*used_len));
|
||||
*used_len+=2;
|
||||
break;
|
||||
default: // 1 byte
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned char)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*out_value=payload[*used_len];
|
||||
*used_len+=1;
|
||||
break;
|
||||
@@ -268,23 +290,37 @@ int get_quic_tlv(char *start_pos, quic_tlv_t *tlv, int len, int type, int thread
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_stream_id(struct streaminfo *pstream, struct _quic_context* _context, char* payload, unsigned char frame_type, int *used_len)
|
||||
int get_stream_id(struct streaminfo *pstream, struct _quic_context* _context, char* payload, int payload_len, unsigned char frame_type, int *used_len)
|
||||
{
|
||||
int stream_len=0,offset_len=0;
|
||||
|
||||
_context->quic_info.frame_hdr.frame_type=frame_type;
|
||||
|
||||
stream_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_ID)+1;
|
||||
if(!check_length(payload_len-*used_len, stream_len))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
_context->quic_info.frame_hdr.stream_id=(unsigned int)get_variable_length(payload, *used_len, stream_len);
|
||||
*used_len+=stream_len; // stream ID length
|
||||
|
||||
if(frame_type&GQUIC_SPECIAL_FRAME_STREAM_DLEN)
|
||||
{
|
||||
if(!check_length(payload_len-*used_len, 2))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
_context->quic_info.frame_hdr.data_len=ntohs(*(unsigned short *)(payload+*used_len));
|
||||
*used_len+=2; //data length
|
||||
}
|
||||
|
||||
offset_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET) ? (((frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET))>>2)+1 : 0;
|
||||
if(!check_length(payload_len-*used_len, offset_len))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
_context->quic_info.frame_hdr.offset=get_variable_length(payload, *used_len, offset_len);
|
||||
*used_len+=offset_len;
|
||||
|
||||
@@ -325,6 +361,7 @@ unsigned long long get_packet_number(char* data, int offset, char pkn_len)
|
||||
// GQUIC version from 0 to 43
|
||||
static enum _QUIC_VERSION parse_q0to43_header(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len)
|
||||
{
|
||||
int ret=0;
|
||||
char public_flags=0;
|
||||
|
||||
struct _quic_public_header *gquic_hdr=&(_context->quic_info.quic_hdr);
|
||||
@@ -380,8 +417,12 @@ static enum _QUIC_VERSION parse_q0to43_header(struct streaminfo *pstream, struct
|
||||
return QUIC_VERSION_UNKNOWN;
|
||||
}
|
||||
|
||||
bit_to_value(payload, gquic_hdr->public_flags>>4, &gquic_hdr->packet_number, used_len);
|
||||
|
||||
ret=bit_to_value(payload, payload_len, gquic_hdr->public_flags>>4, &gquic_hdr->packet_number, used_len);
|
||||
if(ret<0)
|
||||
{
|
||||
return (enum _QUIC_VERSION)gquic_hdr->quic_version;
|
||||
}
|
||||
|
||||
if(gquic_hdr->public_flags==GQUIC_PUBLIC_FLAG_NONCE)
|
||||
{
|
||||
*used_len+=32; //diversification nonce
|
||||
@@ -520,8 +561,8 @@ enum _QUIC_VERSION is_quic_protocol(struct streaminfo *pstream, struct _quic_con
|
||||
(quic_version==GQUIC_VERSION_T099) ||
|
||||
(quic_version>=GQUIC_VERSION_Q047 && quic_version<=GQUIC_VERSION_Q050) ||
|
||||
(quic_version>=GQUIC_VERSION_Q051 && quic_version<=GQUIC_VERSION_Q059) ||
|
||||
(quic_version>=GQUIC_VERSION_T048&& quic_version<=GQUIC_VERSION_T049) ||
|
||||
(quic_version>=GQUIC_VERSION_T050&& quic_version<=GQUIC_VERSION_T059) ||
|
||||
(quic_version>=GQUIC_VERSION_T048 && quic_version<=GQUIC_VERSION_T049) ||
|
||||
(quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
|
||||
(quic_version>=QUANT_VERSION_00 && quic_version<=QUANT_VERSION_FF) ||
|
||||
(quic_version>=QUIC_GO_VERSION_00 && quic_version<=QUIC_GO_VERSION_FF) ||
|
||||
(quic_version>=QUICLY_VERSION_00 && quic_version<=QUICLY_VERSION_FF) ||
|
||||
@@ -647,55 +688,6 @@ int parse_extension_tag(struct streaminfo *pstream, struct _quic_stream **quic_s
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gquic_frame_type_ack(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len, char frame_type, void *a_packet)
|
||||
{
|
||||
unsigned char num_timestamp;
|
||||
unsigned char num_blocks=0;;
|
||||
unsigned short largest_acked_delta_time=0;
|
||||
unsigned long long ack_block_length=0;
|
||||
unsigned long long largest_observed_ack=0;
|
||||
|
||||
bit_to_value(payload, frame_type>>2, &largest_observed_ack, used_len); // frame_type -> LL
|
||||
largest_acked_delta_time=ntohs(*(unsigned short *)(payload+*used_len));
|
||||
*used_len+=sizeof(unsigned short);
|
||||
|
||||
if(frame_type&0x20) // frame_type -> n
|
||||
{
|
||||
num_blocks=(*(unsigned char *)(payload+*used_len))-1;
|
||||
}
|
||||
bit_to_value(payload, frame_type>>2, &ack_block_length, used_len); // frame_type -> mm
|
||||
|
||||
if(num_blocks>0)
|
||||
{
|
||||
*used_len+=1; //gap_to_next_block
|
||||
|
||||
*used_len+=(num_blocks*sizeof(unsigned int)); //Ack block length
|
||||
}
|
||||
|
||||
num_timestamp=*(unsigned char *)(payload+*used_len);
|
||||
*used_len += 1;
|
||||
|
||||
if(num_timestamp > 0)
|
||||
{
|
||||
*used_len+=sizeof(unsigned char); //Delta Largest Observed
|
||||
*used_len+= sizeof(unsigned int); //First Timestamp
|
||||
*used_len+=(num_timestamp-1)*(1+2); //1+2=Delta Largest Observed+Time Since Previous Timestamp
|
||||
}
|
||||
|
||||
MESA_handle_runtime_log(g_quic_param.logger,
|
||||
RLOG_LV_DEBUG,
|
||||
"QUIC_ACK",
|
||||
"largest_observed_ack: %llu largest_acked_delta_time: %u num_blocks: %d ack_block_length: %d num_timestamp: %d addr: %s",
|
||||
largest_observed_ack,
|
||||
largest_acked_delta_time,
|
||||
num_blocks,
|
||||
ack_block_length,
|
||||
num_timestamp,
|
||||
printaddr(&pstream->addr, pstream->threadnum));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gquic_frame_type_stream(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len, void *a_packet)
|
||||
{
|
||||
int ret=0;
|
||||
@@ -703,6 +695,11 @@ int gquic_frame_type_stream(struct streaminfo *pstream, struct _quic_context* _c
|
||||
unsigned short tag_num = 0;
|
||||
unsigned int message_tag;
|
||||
|
||||
if(!check_length(payload_len-*used_len, 8))
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
message_tag=(unsigned int)ntohl(*(unsigned int *)(payload+*used_len));
|
||||
*used_len+=4;
|
||||
|
||||
@@ -762,6 +759,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
return APP_STATE_GIVEME; // PADDING frame
|
||||
break;
|
||||
case GQUIC_REGULAR_FRAME_RST_STREAM:
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned long long)+sizeof(unsigned int)))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
|
||||
*used_len+=sizeof(unsigned int);
|
||||
|
||||
@@ -783,12 +784,21 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
|
||||
break;
|
||||
case GQUIC_REGULAR_FRAME_CONNECTION_CLOSE:
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned short)))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
|
||||
*used_len+=sizeof(unsigned int);
|
||||
|
||||
reason_phrase_length=(unsigned short)get_variable_length(payload, *used_len, sizeof(unsigned short));
|
||||
*used_len+=sizeof(unsigned short);
|
||||
|
||||
if(!check_length(payload_len-*used_len, reason_phrase_length))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
|
||||
*used_len+=reason_phrase_length; // skip Reason Phrase
|
||||
|
||||
MESA_handle_runtime_log(g_quic_param.logger,
|
||||
@@ -802,6 +812,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
|
||||
break;
|
||||
case GQUIC_REGULAR_FRAME_GOAWAY:
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned int)+sizeof(unsigned short)))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
|
||||
*used_len+=sizeof(unsigned int);
|
||||
|
||||
@@ -811,7 +825,11 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
|
||||
reason_phrase_length=(unsigned short)get_variable_length(payload, *used_len, sizeof(unsigned short));
|
||||
*used_len+=sizeof(unsigned short);
|
||||
|
||||
|
||||
if(!check_length(payload_len-*used_len, reason_phrase_length))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
*used_len+=reason_phrase_length; // skip Reason Phrase
|
||||
|
||||
MESA_handle_runtime_log(g_quic_param.logger,
|
||||
@@ -824,6 +842,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
printaddr(&pstream->addr, pstream->threadnum));
|
||||
break;
|
||||
case GQUIC_REGULAR_FRAME_WINDOW_UPDATE:
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned long long)))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
|
||||
*used_len+=sizeof(unsigned int);
|
||||
|
||||
@@ -839,6 +861,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
printaddr(&pstream->addr, pstream->threadnum));
|
||||
break;
|
||||
case GQUIC_REGULAR_FRAME_BLOCKED:
|
||||
if(!check_length(payload_len-*used_len, sizeof(unsigned int)))
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
|
||||
*used_len+=sizeof(unsigned int);
|
||||
|
||||
@@ -850,7 +876,11 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
printaddr(&pstream->addr, pstream->threadnum));
|
||||
break;
|
||||
case GQUIC_REGULAR_FRAME_STOP_WAITING:
|
||||
bit_to_value(payload, _context->quic_info.quic_hdr.public_flags>>4, &least_unacked_delta, used_len);
|
||||
ret=bit_to_value(payload, payload_len, _context->quic_info.quic_hdr.public_flags>>4, &least_unacked_delta, used_len);
|
||||
if(ret<0)
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
|
||||
MESA_handle_runtime_log(g_quic_param.logger,
|
||||
RLOG_LV_DEBUG,
|
||||
@@ -864,14 +894,13 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
//The receiver of a PING frame simply needs to ACK the packet containing this frame
|
||||
break;
|
||||
default: //Regular Frame Types
|
||||
if(frame_type&GQUIC_SPECIAL_FRAME_STREAM)
|
||||
if(frame_type&GQUIC_SPECIAL_FRAME_STREAM || (frame_type&0xC0)==GQUIC_SPECIAL_FRAME_ACK)
|
||||
{
|
||||
stream_id=get_stream_id(pstream, _context, payload, frame_type, used_len);
|
||||
ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
|
||||
}
|
||||
else if((frame_type&0xC0)==GQUIC_SPECIAL_FRAME_ACK) // high bit set 0; (frame_type: 01nullmmB)
|
||||
{
|
||||
stream_id=get_stream_id(pstream, _context, payload, frame_type, used_len);
|
||||
stream_id=get_stream_id(pstream, _context, payload, payload_len, frame_type, used_len);
|
||||
if(stream_id<0)
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
|
||||
}
|
||||
else if((frame_type&0xE0)==GQUIC_SPECIAL_FRAME_CONGEST_FB) // high two bits set 0; (frame_type: 01nullmmB)
|
||||
@@ -898,9 +927,10 @@ int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _cont
|
||||
//QUIC_DATA:is quic data pcap;QUIC_TRUE:is handshake pcap;QUIC_RETURN_DROPME:not quic protocol;
|
||||
int parse_gquic_Q046(struct streaminfo *pstream, struct _quic_context* _context, void *a_packet, char * payload, int payload_len, int *used_len)
|
||||
{
|
||||
int stream_id=0;
|
||||
int ret=APP_STATE_GIVEME;
|
||||
unsigned char frame_type;
|
||||
|
||||
|
||||
while(*used_len < payload_len)
|
||||
{
|
||||
frame_type=payload[*used_len];
|
||||
@@ -908,7 +938,11 @@ int parse_gquic_Q046(struct streaminfo *pstream, struct _quic_context* _context,
|
||||
|
||||
if(frame_type&IQUIC_FRAME_STREAM_HEX08)
|
||||
{
|
||||
get_stream_id(pstream, _context, payload, frame_type, used_len);
|
||||
stream_id=get_stream_id(pstream, _context, payload, payload_len, frame_type, used_len);
|
||||
if(stream_id<0)
|
||||
{
|
||||
return APP_STATE_GIVEME;
|
||||
}
|
||||
ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user