| Index: net/third_party/nss/ssl/ssl3ext.c | 
| diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c | 
| index e54b4fd4c00707fe9f21218378b0fe5e3e0c3e4d..0c6b8e6e7fc4fe88685785eb6b78881e8e501553 100644 | 
| --- a/net/third_party/nss/ssl/ssl3ext.c | 
| +++ b/net/third_party/nss/ssl/ssl3ext.c | 
| @@ -554,12 +554,11 @@ ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *dat | 
| return SECFailure; | 
| } | 
|  | 
| -    ss->ssl3.hs.nextProtoNego = PR_TRUE; | 
| return SECSuccess; | 
| } | 
|  | 
| /* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none | 
| - * of the length may be 0 and the sum of the lengths must equal the length of | 
| + * of the lengths may be 0 and the sum of the lengths must equal the length of | 
| * the block. */ | 
| SECStatus | 
| ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) | 
| @@ -568,63 +567,46 @@ ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) | 
|  | 
| while (offset < length) { | 
| if (data[offset] == 0) { | 
| +	    PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); | 
| return SECFailure; | 
| } | 
| offset += (unsigned int)data[offset] + 1; | 
| } | 
|  | 
| -    if (offset > length) | 
| +    if (offset > length) { | 
| +	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); | 
| return SECFailure; | 
| +    } | 
|  | 
| return SECSuccess; | 
| } | 
|  | 
| SECStatus | 
| ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, | 
| -                                 SECItem *data) | 
| +                                  SECItem *data) | 
| { | 
| -    unsigned int i, j; | 
| SECStatus rv; | 
| -    unsigned char *result; | 
| - | 
| -    if (data->len == 0) { | 
| -	/* The server supports the extension, but doesn't have any | 
| -	 * protocols configured. In this case we request our favoured | 
| -	 * protocol. */ | 
| -	goto pick_first; | 
| -    } | 
| +    unsigned char result[255]; | 
| +    unsigned int result_len; | 
|  | 
| rv = ssl3_ValidateNextProtoNego(data->data, data->len); | 
| if (rv != SECSuccess) | 
| return rv; | 
|  | 
| -    /* For each protocol in server preference order, see if we support it. */ | 
| -    for (i = 0; i < data->len; ) { | 
| -	for (j = 0; j < ss->opt.nextProtoNego.len; ) { | 
| -	    if (data->data[i] == ss->opt.nextProtoNego.data[j] && | 
| -		memcmp(&data->data[i+1], &ss->opt.nextProtoNego.data[j+1], | 
| -		       data->data[i]) == 0) { | 
| -		/* We found a match */ | 
| -		ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; | 
| -		result = &data->data[i]; | 
| -		goto found; | 
| -	    } | 
| -	    j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1; | 
| -	} | 
| - | 
| -	i += (unsigned int)data->data[i] + 1; | 
| -    } | 
| - | 
| -  pick_first: | 
| -    ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; | 
| -    result = ss->opt.nextProtoNego.data; | 
| +    rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, | 
| +                               data->data, data->len, | 
| +                               result, &result_len); | 
| +    if (rv != SECSuccess) | 
| +	return rv; | 
| +    // If the callback wrote more than allowed to |result| it has corrupted our | 
| +    // stack. | 
| +    PORT_Assert(result_len <= sizeof(result)); | 
|  | 
| -  found: | 
| if (ss->ssl3.nextProto.data) | 
| PORT_Free(ss->ssl3.nextProto.data); | 
| -    ss->ssl3.nextProto.data = PORT_Alloc(result[0]); | 
| -    PORT_Memcpy(ss->ssl3.nextProto.data, result + 1, result[0]); | 
| -    ss->ssl3.nextProto.len = result[0]; | 
| +    ss->ssl3.nextProto.data = PORT_Alloc(result_len); | 
| +    PORT_Memcpy(ss->ssl3.nextProto.data, result, result_len); | 
| +    ss->ssl3.nextProto.len = result_len; | 
| return SECSuccess; | 
| } | 
|  | 
| @@ -636,7 +618,7 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, | 
| PRInt32 extension_length; | 
|  | 
| /* Renegotiations do not send this extension. */ | 
| -    if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) { | 
| +    if (!ss->nextProtoCallback || ss->firstHsDone) { | 
| return 0; | 
| } | 
|  | 
|  |