From fe4b09b428734165365b393901016ad0b5862f2f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 20:47:13 +0100 Subject: [PATCH 01/11] IAR: suppress "transfer of control bypasses initialization" warning IAR emits Pe546 a "transfer of control bypasses initialization" diagnostic in many cases that are perfectly valid and idiomatic C. Disable that warning in places where IAR complains. This includes a lot of test suites. Signed-off-by: Gilles Peskine --- library/bignum.c | 9 ++++++++- library/psa_crypto_cipher.c | 9 +++++++++ tests/suites/main_test.function | 10 +++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/library/bignum.c b/library/bignum.c index f6b8f99981..a3ba56575a 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -38,7 +38,14 @@ #include "mbedtls/platform.h" - +#if defined(__IAR_SYSTEMS_ICC__) +/* Suppress a very overeager warning from IAR: it dislikes a forward goto + * that bypasses the initialization of a variable, even if that variable + * is not used after the jump. (This is perfectly valid C; it would only + * be invalid C if jumping into a block from outside that block.) + */ +#pragma diag_suppress=Pe546 // transfer of control bypasses initialization +#endif /* * Conditionally select an MPI sign in constant time. diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c index 7f691c1d95..4d57aac219 100644 --- a/library/psa_crypto_cipher.c +++ b/library/psa_crypto_cipher.c @@ -20,6 +20,15 @@ #include +#if defined(__IAR_SYSTEMS_ICC__) +/* Suppress a very overeager warning from IAR: it dislikes a forward goto + * that bypasses the initialization of a variable, even if that variable + * is not used after the jump. (This is perfectly valid C; it would only + * be invalid C if jumping into a block from outside that block.) + */ +#pragma diag_suppress=Pe546 // transfer of control bypasses initialization +#endif + /* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols * are enabled, but it does not provide any compatibility check between them * (i.e. if the specified key works with the specified algorithm). This helper diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function index 0121f826c7..d1f5e1f686 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -57,6 +57,15 @@ __MBEDTLS_TEST_TEMPLATE__TEST_COMMON_HELPERS /* Test Suite Code */ +#if defined(__IAR_SYSTEMS_ICC__) +/* Suppress a very overeager warning from IAR: it dislikes a forward goto + * that bypasses the initialization of a variable, even if that variable + * is not used after the jump. (This is perfectly valid C; it would only + * be invalid C if jumping into a block from outside that block.) + */ +#pragma diag_suppress=Pe546 // transfer of control bypasses initialization +#endif + #define TEST_SUITE_ACTIVE __MBEDTLS_TEST_TEMPLATE__FUNCTIONS_CODE @@ -221,7 +230,6 @@ static int check_test(size_t func_idx) return ret; } - __MBEDTLS_TEST_TEMPLATE__PLATFORM_CODE #line __MBEDTLS_TEST_TEMPLATE__LINE_NO "suites/main_test.function" From d318227f6286c5fadab08b7962a3b178e23927ea Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 21:54:34 +0100 Subject: [PATCH 02/11] Silence some IAR warnings in SSL code Signed-off-by: Gilles Peskine --- library/ssl_tls.c | 2 +- tests/src/test_helpers/ssl_helpers.c | 26 +++++++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 1185b0b283..4fb2fd96c2 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -10165,7 +10165,7 @@ int mbedtls_ssl_export_keying_material(mbedtls_ssl_context *ssl, int ciphersuite_id = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl); const mbedtls_ssl_ciphersuite_t *ciphersuite = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); - const mbedtls_md_type_t hash_alg = ciphersuite->mac; + const mbedtls_md_type_t hash_alg = (mbedtls_md_type_t) ciphersuite->mac; switch (mbedtls_ssl_get_version_number(ssl)) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 7fb23ab829..b4ac4a3bc8 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -11,6 +11,15 @@ #include #include "mbedtls/psa_util.h" +#if defined(__IAR_SYSTEMS_ICC__) +/* Suppress a very overeager warning from IAR: it dislikes a forward goto + * that bypasses the initialization of a variable, even if that variable + * is not used after the jump. (This is perfectly valid C; it would only + * be invalid C if jumping into a block from outside that block.) + */ +#pragma diag_suppress=Pe546 // transfer of control bypasses initialization +#endif + #if defined(MBEDTLS_SSL_TLS_C) int mbedtls_test_random(void *p_rng, unsigned char *output, size_t output_len) { @@ -1283,12 +1292,15 @@ static void mbedtls_test_ssl_cipher_info_from_type(mbedtls_cipher_type_t cipher_ int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, mbedtls_ssl_transform *t_out, - int cipher_type, int hash_id, + int cipher_type_arg, int md_type_arg, int etm, int tag_mode, mbedtls_ssl_protocol_version tls_version, size_t cid0_len, size_t cid1_len) { + mbedtls_md_type_t md_type = (mbedtls_md_type_t) md_type_arg; + mbedtls_cipher_type_t cipher_type = (mbedtls_cipher_type_t) cipher_type_arg; + mbedtls_cipher_mode_t cipher_mode = MBEDTLS_MODE_NONE; size_t key_bits = 0; int ret = 0; @@ -1319,7 +1331,7 @@ int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ maclen = 0; - mbedtls_test_ssl_cipher_info_from_type((mbedtls_cipher_type_t) cipher_type, + mbedtls_test_ssl_cipher_info_from_type(cipher_type, &cipher_mode, &key_bits, &ivlen); /* Pick keys */ @@ -1334,7 +1346,7 @@ int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* Pick cipher */ - cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) cipher_type); + cipher_info = mbedtls_cipher_info_from_type(cipher_type); CHK(cipher_info != NULL); CHK(mbedtls_cipher_info_get_iv_size(cipher_info) <= 16); CHK(mbedtls_cipher_info_get_key_bitlen(cipher_info) % 8 == 0); @@ -1381,10 +1393,10 @@ int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, if (cipher_mode == MBEDTLS_MODE_CBC || cipher_mode == MBEDTLS_MODE_STREAM) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) - mbedtls_md_info_t const *md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) hash_id); + mbedtls_md_info_t const *md_info = mbedtls_md_info_from_type(md_type); CHK(md_info != NULL); #endif - maclen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) hash_id); + maclen = mbedtls_md_get_size_from_type(md_type); CHK(maclen != 0); /* Pick hash keys */ CHK((md0 = mbedtls_calloc(1, maclen)) != NULL); @@ -1393,7 +1405,7 @@ int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, memset(md1, 0x6, maclen); #if defined(MBEDTLS_USE_PSA_CRYPTO) - alg = mbedtls_md_psa_alg_from_type(hash_id); + alg = mbedtls_md_psa_alg_from_type(md_type); CHK(alg != 0); @@ -1450,7 +1462,7 @@ int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, #endif } #else - ((void) hash_id); + (void) md_type; #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ From c7496f7b578987b2434a82692a9758d44fa0a3bf Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 20:48:20 +0100 Subject: [PATCH 03/11] Improve non-portable EINVAL check for strtol Standard C doesn't have `EINVAL`. Check for invalid inputs in a portable way. Signed-off-by: Gilles Peskine --- tests/suites/host_test.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function index 90b050e129..b8d1d8596d 100644 --- a/tests/suites/host_test.function +++ b/tests/suites/host_test.function @@ -39,7 +39,7 @@ static int verify_int(char *str, intmax_t *p_value) /* Limit the range to long: for large integers, the test framework will * use expressions anyway. */ long value = strtol(str, &end, 0); - if (errno == EINVAL || *end != '\0') { + if (*end != '\0' || end == str) { mbedtls_fprintf(stderr, "Expected integer for parameter and got: %s\n", str); return KEY_VALUE_MAPPING_NOT_FOUND; From 8554fcec0dc193fbc92d87470e7d0e5eb1574bff Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 20:52:45 +0100 Subject: [PATCH 04/11] IAR: allow test code to use stdio Signed-off-by: Gilles Peskine --- tests/suites/main_test.function | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function index d1f5e1f686..af34bfc76b 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -34,6 +34,12 @@ #endif #endif +#if defined(__IAR_SYSTEMS_ICC__) +/* With IAR, enable support for ::FILE functions in stdio.h. + */ +#define _DLIB_FILE_DESCRIPTOR 1 +#endif + #include "mbedtls/build_info.h" /* Test code may use deprecated identifiers only if the preprocessor symbol From 2d88255d139ac7db6c080792331da552350e6cba Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 22:09:23 +0100 Subject: [PATCH 05/11] Remove unused variable Signed-off-by: Gilles Peskine --- tests/suites/test_suite_alignment.function | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/suites/test_suite_alignment.function b/tests/suites/test_suite_alignment.function index 240f55211e..da3b175e29 100644 --- a/tests/suites/test_suite_alignment.function +++ b/tests/suites/test_suite_alignment.function @@ -158,12 +158,6 @@ void mbedtls_byteswap(char *input_str, int size, char *expected_str) /* BEGIN_CASE */ void get_byte() { - uint8_t data[16]; - - for (size_t i = 0; i < sizeof(data); i++) { - data[i] = (uint8_t) i; - } - uint64_t u64 = 0x0706050403020100; for (size_t b = 0; b < 8; b++) { uint8_t expected = b; From 20a60132ab367e0a766436d624998ee0d674f7b6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 23:13:25 +0100 Subject: [PATCH 06/11] Temporarily silence IAR warning about enum conversions Temporarily suppress a perfectly reasonable warning from IAR that comes up very often in our unit tests: silent conversion of int to an enum type. Improvement tracked as https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/707 Signed-off-by: Gilles Peskine --- tests/suites/main_test.function | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function index af34bfc76b..11a832f8e8 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -70,6 +70,15 @@ __MBEDTLS_TEST_TEMPLATE__TEST_COMMON_HELPERS * be invalid C if jumping into a block from outside that block.) */ #pragma diag_suppress=Pe546 // transfer of control bypasses initialization + +/* Temporarily suppress a perfectly reasonable warning from IAR that + * comes up very often in our unit tests: silent conversion of int to + * an enum type. + * + * Remove this when https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/707 + * is fixed. + */ +#pragma diag_suppress=Pe188 // enumerated type mixed with another type #endif #define TEST_SUITE_ACTIVE From fd65f0eaabb4849114cfad94e4653c69cfa2ebdf Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 23:14:07 +0100 Subject: [PATCH 07/11] Fix build error on some platforms where NULL is defined as 0 If `NULL` is an integer constant expression with the value 0 (which C allows), the expression `prng ? NULL : NULL` is not an integer constant expression so it is not a null pointer constant, and thus it is not a pointer. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_rsa.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function index 98ea9efb1c..5a30cf079a 100644 --- a/tests/suites/test_suite_rsa.function +++ b/tests/suites/test_suite_rsa.function @@ -1190,7 +1190,7 @@ void mbedtls_rsa_validate_params(char *input_N, have_D ? &D : NULL, have_E ? &E : NULL, prng ? mbedtls_test_rnd_std_rand : NULL, - prng ? NULL : NULL) == result); + NULL) == result); exit: mbedtls_mpi_free(&N); From 433a14f96ec04e9a9454f4e4bbc822d6bc409ff7 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 23:16:57 +0100 Subject: [PATCH 08/11] Use TEST_FAIL rather than a TEST_ASSERT(!"...") hack This gets rid of a warning from IAR. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_psa_crypto.function | 24 +++++++++---------- .../test_suite_psa_crypto_pake.function | 24 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index b4ff66ae9f..596dd1fe9e 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -836,8 +836,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if (inject_error == 1) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -942,8 +942,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if (inject_error == 1) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -1010,8 +1010,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if (inject_error == 2) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } break; @@ -1077,8 +1077,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if (inject_error == 3) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -1137,8 +1137,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if (inject_error == 3) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -1177,8 +1177,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if (inject_error == 4) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } break; diff --git a/tests/suites/test_suite_psa_crypto_pake.function b/tests/suites/test_suite_psa_crypto_pake.function index 08c88a1d6e..3a6911dc2f 100644 --- a/tests/suites/test_suite_psa_crypto_pake.function +++ b/tests/suites/test_suite_psa_crypto_pake.function @@ -252,8 +252,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if ((err_stage >= ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1) && (err_stage <= ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2)) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -346,8 +346,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if ((err_stage >= ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1) && (err_stage <= ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2)) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -379,8 +379,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if ((err_stage >= ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1) && (err_stage <= ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2)) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } break; @@ -435,8 +435,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if ((err_stage >= ERR_INJECT_ROUND2_SERVER_KEY_SHARE) && (err_stage <= ERR_INJECT_ROUND2_SERVER_ZK_PROOF)) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -499,8 +499,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if ((err_stage >= ERR_INJECT_ROUND2_SERVER_KEY_SHARE) && (err_stage <= ERR_INJECT_ROUND2_SERVER_ZK_PROOF)) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } } @@ -526,8 +526,8 @@ static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive, /* Error didn't trigger, make test fail */ if ((err_stage >= ERR_INJECT_ROUND2_CLIENT_KEY_SHARE) && (err_stage <= ERR_INJECT_ROUND2_CLIENT_ZK_PROOF)) { - TEST_ASSERT( - !"One of the last psa_pake_input() calls should have returned the expected error."); + TEST_FAIL( + "One of the last psa_pake_input() calls should have returned the expected error."); } break; From b340f0b7801b8dbcc0f5bbb6c4414541999e4ef6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 22:38:47 +0100 Subject: [PATCH 09/11] Fix the build on non-Unix platforms when MBEDTLS_FS_IO is disabled Don't try to include a Unix header when we don't need one. The tests will still fail to build if `MBEDTLS_FS_IO` is enabled and the platform has stdio but not Unix extensions. (This is also the case for some of our X.509 library code.) Signed-off-by: Gilles Peskine --- tests/suites/test_suite_pkcs7.function | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function index e5dc4bd192..6dc9d3d395 100644 --- a/tests/suites/test_suite_pkcs7.function +++ b/tests/suites/test_suite_pkcs7.function @@ -6,10 +6,14 @@ #include "mbedtls/x509_crl.h" #include "x509_internal.h" #include "mbedtls/oid.h" -#include "sys/types.h" -#include "sys/stat.h" #include "mbedtls/rsa.h" #include "mbedtls/error.h" + +#if defined(MBEDTLS_FS_IO) +#include "sys/types.h" +#include "sys/stat.h" +#endif + /* END_HEADER */ /* BEGIN_DEPENDENCIES From d0e9891a47d6d7f1f7ede16ab669833e0982b77e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 11 Mar 2026 23:22:52 +0100 Subject: [PATCH 10/11] Fix tricky comment Signed-off-by: Gilles Peskine --- tests/suites/test_suite_ecdh.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index 300916feaa..cc891a0d13 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -473,7 +473,7 @@ void ecdh_context_grp(int id) mbedtls_ecdh_init(&srv); TEST_ASSERT(mbedtls_ecdh_setup(&srv, id) == 0); - /* Test the retrieved group id matches/*/ + /* Test the retrieved group id matches */ TEST_ASSERT((int) mbedtls_ecdh_get_grp_id(&srv) == id); exit: From f5e1cb21c8d7ba9c0a2c0450afac524bab9e819c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 20 Mar 2026 21:21:41 +0100 Subject: [PATCH 11/11] Add changelog entry Even without CI validation, we can promise that we've made the situation better, and an IAR warning has been reported in https://github.com/Mbed-TLS/mbedtls/issues/10648 Signed-off-by: Gilles Peskine --- ChangeLog.d/iar-4.1.0.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 ChangeLog.d/iar-4.1.0.txt diff --git a/ChangeLog.d/iar-4.1.0.txt b/ChangeLog.d/iar-4.1.0.txt new file mode 100644 index 0000000000..d4c1417dad --- /dev/null +++ b/ChangeLog.d/iar-4.1.0.txt @@ -0,0 +1,2 @@ +Bugfix + * Fix some IAR warnings. Fixes #10648.