next_packet:
static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen){    struct rdpkt1_state_tag *st = &ssh->rdpkt1_state;    crBegin(ssh->ssh1_rdpkt_crstate);  next_packet:    st->pktin = ssh_new_packet();    st->pktin->type = 0;    st->pktin->length = 0;    for (st->i = st->len = 0; st->i < 4; st->i++) {	while ((*datalen) == 0)	    crReturn(NULL);	st->len = (st->len << 8) + **data;	(*data)++, (*datalen)--;    }    st->pad = 8 - (st->len % 8);    st->biglen = st->len + st->pad;    st->pktin->length = st->len - 5;    if (st->biglen < 0) {        bombout(("Extremely large packet length from server suggests"		 " data stream corruption"));	ssh_free_packet(st->pktin);        crStop(NULL);    }    st->pktin->maxlen = st->biglen;    st->pktin->data = snewn(st->biglen + APIEXTRA, unsigned char);    st->to_read = st->biglen;    st->p = st->pktin->data;    while (st->to_read > 0) {	st->chunk = st->to_read;	while ((*datalen) == 0)	    crReturn(NULL);	if (st->chunk > (*datalen))	    st->chunk = (*datalen);	memcpy(st->p, *data, st->chunk);	*data += st->chunk;	*datalen -= st->chunk;	st->p += st->chunk;	st->to_read -= st->chunk;    }    if (ssh->cipher && detect_attack(ssh->crcda_ctx, st->pktin->data,				     st->biglen, NULL)) {        bombout(("Network attack (CRC compensation) detected!"));	ssh_free_packet(st->pktin);        crStop(NULL);    }    if (ssh->cipher)	ssh->cipher->decrypt(ssh->v1_cipher_ctx, st->pktin->data, st->biglen);    st->realcrc = crc32_compute(st->pktin->data, st->biglen - 4);    st->gotcrc = GET_32BIT(st->pktin->data + st->biglen - 4);    if (st->gotcrc != st->realcrc) {	bombout(("Incorrect CRC received on packet"));	ssh_free_packet(st->pktin);	crStop(NULL);    }    st->pktin->body = st->pktin->data + st->pad + 1;    st->pktin->savedpos = 0;    if (ssh->v1_compressing) {	unsigned char *decompblk;	int decomplen;	if (!zlib_decompress_block(ssh->sc_comp_ctx,				   st->pktin->body - 1, st->pktin->length + 1,				   &decompblk, &decomplen)) {	    bombout(("Zlib decompression encountered invalid data"));	    ssh_free_packet(st->pktin);	    crStop(NULL);	}	if (st->pktin->maxlen < st->pad + decomplen) {	    st->pktin->maxlen = st->pad + decomplen;	    st->pktin->data = sresize(st->pktin->data,				      st->pktin->maxlen + APIEXTRA,				      unsigned char);	    st->pktin->body = st->pktin->data + st->pad + 1;	}	memcpy(st->pktin->body - 1, decompblk, decomplen);	sfree(decompblk);	st->pktin->length = decomplen - 1;    }    st->pktin->type = st->pktin->body[-1];    /*     * Log incoming packet, possibly omitting sensitive fields.     */    if (ssh->logctx) {	int nblanks = 0;	struct logblank_t blank;	if (ssh->cfg.logomitdata) {	    int do_blank = FALSE, blank_prefix = 0;	    /* "Session data" packets - omit the data field */	    if ((st->pktin->type == SSH1_SMSG_STDOUT_DATA) ||		(st->pktin->type == SSH1_SMSG_STDERR_DATA)) {		do_blank = TRUE; blank_prefix = 0;	    } else if (st->pktin->type == SSH1_MSG_CHANNEL_DATA) {		do_blank = TRUE; blank_prefix = 4;	    }	    if (do_blank) {		blank.offset = blank_prefix;		blank.len = st->pktin->length;		blank.type = PKTLOG_OMIT;		nblanks = 1;	    }	}	log_packet(ssh->logctx,		   PKT_INCOMING, st->pktin->type,		   ssh1_pkt_type(st->pktin->type),		   st->pktin->body, st->pktin->length,		   nblanks, &blank);    }    if (st->pktin->type == SSH1_SMSG_STDOUT_DATA ||	st->pktin->type == SSH1_SMSG_STDERR_DATA ||	st->pktin->type == SSH1_MSG_DEBUG ||	st->pktin->type == SSH1_SMSG_AUTH_TIS_CHALLENGE ||	st->pktin->type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) {	long stringlen = GET_32BIT(st->pktin->body);	if (stringlen + 4 != st->pktin->length) {	    bombout(("Received data packet with bogus string length"));	    ssh_free_packet(st->pktin);	    crStop(NULL);	}    }    if (st->pktin->type == SSH1_MSG_DEBUG) {        char *buf, *msg;        int msglen;        ssh_pkt_getstring(st->pktin, &msg, &msglen);        buf = dupprintf("Remote debug message: %.*s", msglen, msg);	logevent(buf);        sfree(buf);	ssh_free_packet(st->pktin);	goto next_packet;    } else if (st->pktin->type == SSH1_MSG_IGNORE) {	/* do nothing */	ssh_free_packet(st->pktin);	goto next_packet;    }    if (st->pktin->type == SSH1_MSG_DISCONNECT) {	/* log reason code in disconnect message */	char *msg;	int msglen;        ssh_pkt_getstring(st->pktin, &msg, &msglen);	bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg));	ssh_free_packet(st->pktin);	crStop(NULL);    }    crFinish(st->pktin);}