diff --git a/ext/mysqli/tests/fake_server.inc b/ext/mysqli/tests/fake_server.inc index b02fabc584c5d..0a7c4ab38c052 100644 --- a/ext/mysqli/tests/fake_server.inc +++ b/ext/mysqli/tests/fake_server.inc @@ -611,6 +611,13 @@ class my_mysqli_fake_server_conn $packets = $this->packet_generator->server_query_execute_data_response($field_name); $this->send($this->packets_to_bytes($packets), "Query execute data $field_name"); } + + public function send_too_short_server_ok() + { + $packet = $this->packet_generator->server_ok(); + $packet->packet_length = "060000"; + $this->send($packet->to_bytes(), "Server OK"); + } } class my_mysqli_fake_server_process @@ -807,6 +814,18 @@ function my_mysqli_test_query_response_row_read_two_fields(my_mysqli_fake_server } } +function my_mysqli_test_invalid_greeting_packet(my_mysqli_fake_server_conn $conn): void +{ + // Send nothing at all to the client +} + +function my_mysqli_test_ok_packet_too_short(my_mysqli_fake_server_conn $conn): void +{ + $conn->send_server_greetings(); + $conn->read(); + $conn->send_too_short_server_ok(); +} + function run_fake_server(string $test_function, $port = 33305): void { $address = '127.0.0.1'; diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt index db54a6c0177a1..42b5787802ed5 100644 --- a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt +++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt @@ -19,7 +19,7 @@ try { $info = mysqli_info($conn); var_dump($info); } catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; + echo 'ERROR: ' . $e->getMessage() . PHP_EOL; } $process->terminate(); @@ -32,7 +32,5 @@ print "done!"; [*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 [*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 [*] Sending - Malicious OK Auth Response [Extract heap through buffer over-read]: 0900000200000002000000fcff - -Warning: mysqli::__construct(): OK packet message length is past the packet size in %s on line %d -Unknown error while trying to connect via tcp://127.0.0.1:50001 +ERROR: OK packet message length is past the packet size done! diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt index 77f2232eca687..1d8ec08367193 100644 --- a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt +++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt @@ -19,12 +19,10 @@ $conn = new mysqli($servername, $username, $password, "", $port); echo "[*] Running query on the fake server...\n"; -$result = $conn->query("SELECT * from users"); - -if ($result) { - $all_fields = $result->fetch_fields(); - var_dump($result->fetch_all(MYSQLI_ASSOC)); - var_dump(get_object_vars($all_fields[0])["def"]); +try { + $result = $conn->query("SELECT * from users"); +} catch (mysqli_sql_exception $exception) { + echo 'ERROR: ' . $exception->getMessage() . PHP_EOL; } $conn->close(); @@ -42,6 +40,5 @@ print "done!"; [*] Running query on the fake server... [*] Received: 140000000353454c454354202a2066726f6d207573657273 [*] Sending - Malicious Tabular Response [Extract heap through buffer over-read]: 01000001011e0000020164016401640164016401640c3f000b000000030350000000fd000001aa05000003fe00002200040000040135017405000005fe00002200 - -Warning: mysqli::query(): Protocol error. Server sent default for unsupported field list (mysqlnd_wireprotocol.c:%d) in %s on line %d +ERROR: Server sent default for unsupported field list done! diff --git a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt index 0b4db8ccece95..35aace2bec934 100644 --- a/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt +++ b/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt @@ -17,7 +17,12 @@ $process->wait(); $conn = new mysqli($servername, $username, $password, "", $port); echo "[*] Running query on the fake server...\n"; -$result = $conn->query("SELECT * from users"); +try { + $result = $conn->query("SELECT * from users"); +} catch (mysqli_sql_exception $exception) { + echo 'ERROR: ' . $exception->getMessage() . PHP_EOL; +} + $info = mysqli_info($conn); var_dump($info); @@ -35,9 +40,6 @@ print "done!"; [*] Running query on the fake server... [*] Received: 140000000353454c454354202a2066726f6d207573657273 [*] Sending - Malicious Tabular Response [Extract heap through buffer over-read]: 0900000100000000000000fa65 - -Warning: mysqli::query(): RSET_HEADER packet additional data length is past 249 bytes the packet size in %s on line %d - -Warning: mysqli::query(): Error reading result set's header in %s on line %d +ERROR: RSET_HEADER packet additional data length is past the packet size NULL done! diff --git a/ext/mysqli/tests/wireprotocol_errors/AUTH_RESPONSE_packet_is_shorter_than_expected.phpt b/ext/mysqli/tests/wireprotocol_errors/AUTH_RESPONSE_packet_is_shorter_than_expected.phpt new file mode 100644 index 0000000000000..20924d7d39514 --- /dev/null +++ b/ext/mysqli/tests/wireprotocol_errors/AUTH_RESPONSE_packet_is_shorter_than_expected.phpt @@ -0,0 +1,36 @@ +--TEST-- +AUTH_RESPONSE packet is shorter than expected +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +try { + $conn = new mysqli( $servername, $username, $password, "", $port ); +} catch (Exception $e) { + echo 'ERROR: ' . $e->getMessage() . PHP_EOL; +} + +$process->terminate(); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0600000200000002000000 + +Warning: mysqli::__construct(): Premature end of data (mysqlnd_wireprotocol.c:732) in %s +ERROR: AUTH_RESPONSE packet is shorter than expected +done! diff --git a/ext/mysqli/tests/wireprotocol_errors/error_while_reading_greeting_packet.phpt b/ext/mysqli/tests/wireprotocol_errors/error_while_reading_greeting_packet.phpt new file mode 100644 index 0000000000000..d012a2acd9df9 --- /dev/null +++ b/ext/mysqli/tests/wireprotocol_errors/error_while_reading_greeting_packet.phpt @@ -0,0 +1,31 @@ +--TEST-- +Error while reading greeting packet +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +try { + $conn = new mysqli( $servername, $username, $password, "", $port ); +} catch (Exception $e) { + echo 'ERROR: ' . $e->getMessage() . PHP_EOL; +} + +$process->terminate(); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +ERROR: Error while reading greeting packet +done! diff --git a/ext/mysqlnd/mysqlnd_commands.c b/ext/mysqlnd/mysqlnd_commands.c index 27a5f13a30746..d889b5afbad64 100644 --- a/ext/mysqlnd/mysqlnd_commands.c +++ b/ext/mysqlnd/mysqlnd_commands.c @@ -594,8 +594,7 @@ MYSQLND_METHOD(mysqlnd_command, handshake)(MYSQLND_CONN_DATA * const conn, const conn->payload_decoder_factory->m.init_greet_packet(&greet_packet); if (FAIL == PACKET_READ(conn, &greet_packet)) { - DBG_ERR("Error while reading greeting packet"); - php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid()); + SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Error while reading greeting packet"); goto err; } else if (greet_packet.error_no) { DBG_ERR_FMT("errorno=%u error=%s", greet_packet.error_no, greet_packet.error); diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 5fad5281947ea..d66800ecb7b56 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -307,6 +307,8 @@ mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s) conn->payload_decoder_factory->m.init_prepare_response_packet(&prepare_resp); if (FAIL == PACKET_READ(conn, &prepare_resp)) { + // There might have been a connection specific error which we must report as a statement error + COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info); goto done; } diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index ae8dc77b4cd9a..81f6ae83eb8df 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -183,9 +183,6 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s) UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status); if (FAIL == (ret = PACKET_READ(conn, &rset_header))) { - if (conn->error_info->error_no != CR_SERVER_GONE_ERROR && conn->error_info->error_no != CR_CLIENT_INTERACTION_TIMEOUT) { - php_error_docref(NULL, E_WARNING, "Error reading result set's header"); - } break; } diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 36fd532337375..8706d0e3d6678 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -491,9 +491,7 @@ php_mysqlnd_greet_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("GREET packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "GREET packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "GREET packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -738,8 +736,7 @@ php_mysqlnd_auth_response_read(MYSQLND_CONN_DATA * conn, void * _packet) /* p can get past packet size when getting field length so it needs to be checked first * and after that it can be checked that the net_len is not greater than the packet size */ if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < net_len) { - DBG_ERR_FMT("OK packet message length is past the packet size"); - php_error_docref(NULL, E_WARNING, "OK packet message length is past the packet size"); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "OK packet message length is past the packet size"); DBG_RETURN(FAIL); } packet->message_len = net_len; @@ -756,9 +753,7 @@ php_mysqlnd_auth_response_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("OK packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "AUTH_RESPONSE packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "AUTH_RESPONSE packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -893,9 +888,7 @@ php_mysqlnd_ok_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("OK packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "OK packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "OK packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -980,9 +973,7 @@ php_mysqlnd_eof_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("EOF packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "EOF packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "EOF packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -1067,6 +1058,9 @@ php_mysqlnd_rset_header_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_ENTER("php_mysqlnd_rset_header_read"); if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "resultset header", PROT_RSET_HEADER_PACKET)) { + if (!error_info->error_no) { + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Error reading result set's header"); + } DBG_RETURN(FAIL); } BAIL_IF_NO_MORE_DATA; @@ -1125,12 +1119,7 @@ php_mysqlnd_rset_header_read(MYSQLND_CONN_DATA * conn, void * _packet) /* p can get past packet size when getting field length so it needs to be checked first * and after that it can be checked that the len is not greater than the packet size */ if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < len) { - size_t local_file_name_over_read = ((p - buf) - packet->header.size) + len; - DBG_ERR_FMT("RSET_HEADER packet additional data length is past %zu bytes the packet size", - local_file_name_over_read); - php_error_docref(NULL, E_WARNING, - "RSET_HEADER packet additional data length is past %zu bytes the packet size", - local_file_name_over_read); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "RSET_HEADER packet additional data length is past the packet size"); DBG_RETURN(FAIL); } packet->info_or_local_file.s = mnd_emalloc(len + 1); @@ -1151,9 +1140,7 @@ php_mysqlnd_rset_header_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(ret); premature_end: - DBG_ERR_FMT("RSET_HEADER packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "RSET_HEADER packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "RSET_HEADER packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -1229,8 +1216,7 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); } else if (EODATA_MARKER == *p && packet->header.size < 8) { /* Premature EOF. That should be COM_FIELD_LIST. But we don't support COM_FIELD_LIST anymore, thus this should not happen */ - DBG_ERR("Premature EOF. That should be COM_FIELD_LIST"); - php_error_docref(NULL, E_WARNING, "Premature EOF in result field metadata"); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Premature EOF in result field metadata"); DBG_RETURN(FAIL); } @@ -1245,12 +1231,10 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet) /* 1 byte length */ if (UNEXPECTED(12 != *p)) { - DBG_ERR_FMT("Protocol error. Server sent false length. Expected 12 got %d", (int) *p); - php_error_docref(NULL, E_WARNING, "Protocol error. Server sent false length. Expected 12"); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Protocol error. Server sent false length. Expected 12"); } if ((size_t)((p - begin) + 12) > packet->header.size) { - php_error_docref(NULL, E_WARNING, "Premature end of data (mysqlnd_wireprotocol.c:%u)", __LINE__); goto premature_end; } @@ -1288,10 +1272,7 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet) (len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH) { - DBG_ERR_FMT("Protocol error. Server sent default for unsupported field list"); - php_error_docref(NULL, E_WARNING, - "Protocol error. Server sent default for unsupported field list (mysqlnd_wireprotocol.c:%u)", - __LINE__); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Server sent default for unsupported field list"); DBG_RETURN(FAIL); } @@ -1349,14 +1330,10 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); faulty_or_fake: - DBG_ERR_FMT("Protocol error. Server sent NULL_LENGTH. The server is faulty"); - php_error_docref(NULL, E_WARNING, "Protocol error. Server sent NULL_LENGTH." - " The server is faulty"); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Protocol error. Server sent NULL_LENGTH. The server is faulty"); DBG_RETURN(FAIL); premature_end: - DBG_ERR_FMT("RSET field packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "Result set field packet %zu bytes " - "shorter than expected", p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Result set field packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -1862,9 +1839,9 @@ php_mysqlnd_prepare_read(MYSQLND_CONN_DATA * conn, void * _packet) if (data_size != PREPARE_RESPONSE_SIZE_41 && data_size != PREPARE_RESPONSE_SIZE_50 && - !(data_size > PREPARE_RESPONSE_SIZE_50)) { + data_size <= PREPARE_RESPONSE_SIZE_50) { DBG_ERR_FMT("Wrong COM_STMT_PREPARE response size. Received %u", data_size); - php_error(E_WARNING, "Wrong COM_STMT_PREPARE response size. Received %u", data_size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Wrong COM_STMT_PREPARE response size"); DBG_RETURN(FAIL); } @@ -1896,9 +1873,7 @@ php_mysqlnd_prepare_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("PREPARE packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "PREPARE packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "PREPARE packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -1966,9 +1941,7 @@ php_mysqlnd_chg_user_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("CHANGE_USER packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "CHANGE_USER packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "CHANGE_USER packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -2050,9 +2023,7 @@ php_mysqlnd_sha256_pk_request_response_read(MYSQLND_CONN_DATA * conn, void * _pa DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("OK packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "SHA256_PK_REQUEST_RESPONSE packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "SHA256_PK_REQUEST_RESPONSE packet is shorter than expected"); DBG_RETURN(FAIL); } /* }}} */ @@ -2163,9 +2134,7 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); premature_end: - DBG_ERR_FMT("OK packet %zu bytes shorter than expected", p - begin - packet->header.size); - php_error_docref(NULL, E_WARNING, "SHA256_PK_REQUEST_RESPONSE packet %zu bytes shorter than expected", - p - begin - packet->header.size); + SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "SHA256_PK_REQUEST_RESPONSE packet is shorter than expected"); DBG_RETURN(FAIL); } @@ -2615,7 +2584,7 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_response)( MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory, const enum mysqlnd_packet_type ok_packet, - const bool silent, + const bool silent, /* This is a dead parameter */ const enum php_mysqlnd_server_command command, const bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */ @@ -2638,12 +2607,8 @@ MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_response)( break; default: SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet"); - php_error_docref(NULL, E_ERROR, "Wrong response packet %u passed to the function", ok_packet); break; } - if (!silent && error_info->error_no == CR_MALFORMED_PACKET) { - php_error_docref(NULL, E_WARNING, "Error while reading %s's response packet. PID=%d", mysqlnd_command_to_text[command], getpid()); - } DBG_INF(ret == PASS ? "PASS":"FAIL"); DBG_RETURN(ret); }