Commit cbe0144ab49 for php.net

commit cbe0144ab49e542ca25677f66c71e4e1b9b23273
Author: Pratik Bhujel <prateekbhujelpb@gmail.com>
Date:   Tue Apr 7 00:19:25 2026 +0545

    ext/snmp: promote invalid-input warnings to ValueError (#21319)

    This now also specifies which argument is causing the error.

diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index 1daa51851fb..6c219d376e5 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -655,7 +655,8 @@ static void php_free_objid_query(struct objid_query *objid_query, HashTable* oid
 */
 static bool php_snmp_parse_oid(
 	zval *object, int st, struct objid_query *objid_query, zend_string *oid_str, HashTable *oid_ht,
-	zend_string *type_str, HashTable *type_ht, zend_string *value_str, HashTable *value_ht
+	zend_string *type_str, HashTable *type_ht, zend_string *value_str, HashTable *value_ht,
+	uint32_t oid_argument_offset, uint32_t type_argument_offset, uint32_t value_argument_offset
 ) {
 	char *pptr;
 	uint32_t idx_type = 0, idx_value = 0;
@@ -682,7 +683,7 @@ static bool php_snmp_parse_oid(
 			ZEND_ASSERT(type_str && value_str);

 			if (ZSTR_LEN(type_str) != 1) {
-				zend_value_error("Type must be a single character");
+				zend_argument_value_error(type_argument_offset, "must be a single character");
 				efree(objid_query->vars);
 				return false;
 			}
@@ -693,7 +694,7 @@ static bool php_snmp_parse_oid(
 		objid_query->count++;
 	} else if (oid_ht) { /* we got objid array */
 		if (zend_hash_num_elements(oid_ht) == 0) {
-			zend_value_error("Array of object IDs must not be empty");
+			zend_argument_value_error(oid_argument_offset, "must not be empty when passed as an array");
 			return false;
 		}
 		objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(oid_ht), 0);
@@ -738,14 +739,14 @@ static bool php_snmp_parse_oid(
 						char ptype = *ZSTR_VAL(type);
 						zend_string_release(type);
 						if (len != 1) {
-							zend_value_error("Type must be a single character");
+							zend_argument_value_error(type_argument_offset, "must be a single character");
 							php_free_objid_query(objid_query, oid_ht, value_ht, st);
 							return false;
 						}
 						objid_query->vars[objid_query->count].type = ptype;
 						idx_type++;
 					} else {
-						php_error_docref(NULL, E_WARNING, "'%s': no type set", ZSTR_VAL(tmp));
+						zend_argument_value_error(type_argument_offset, "must contain a type for object ID '%s'", ZSTR_VAL(tmp));
 						php_free_objid_query(objid_query, oid_ht, value_ht, st);
 						return false;
 					}
@@ -780,7 +781,7 @@ static bool php_snmp_parse_oid(
 						objid_query->vars[objid_query->count].value = ZSTR_VAL(tmp);
 						idx_value++;
 					} else {
-						php_error_docref(NULL, E_WARNING, "'%s': no value set", ZSTR_VAL(tmp));
+						zend_argument_value_error(value_argument_offset, "must contain a value for object ID '%s'", ZSTR_VAL(tmp));
 						php_free_objid_query(objid_query, oid_ht, value_ht, st);
 						return false;
 					}
@@ -827,7 +828,7 @@ static bool php_snmp_parse_oid(
 /* {{{ snmp_session_init
 	allocates memory for session and session->peername, caller should free it manually using snmp_session_free() and efree()
 */
-static bool snmp_session_init(php_snmp_session **session_p, int version, zend_string *hostname, zend_string *community, zend_long timeout, zend_long retries, int timeout_argument_offset)
+static bool snmp_session_init(php_snmp_session **session_p, int version, zend_string *hostname, zend_string *community, zend_long timeout, zend_long retries, int hostname_argument_offset, int timeout_argument_offset)
 {
 	php_snmp_session *session;
 	char *pptr, *host_ptr;
@@ -841,23 +842,13 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st
 	ZEND_ASSERT(hostname != NULL);
 	ZEND_ASSERT(community != NULL);

-	if (zend_str_has_nul_byte(hostname)) {
-		zend_argument_value_error(2, "must not contain any null bytes");
-		return false;
-	}
-
 	if (ZSTR_LEN(hostname) >= MAX_NAME_LEN) {
-		zend_argument_value_error(2, "length must be lower than %d", MAX_NAME_LEN);
-		return false;
-	}
-
-	if (zend_str_has_nul_byte(community)) {
-		zend_argument_value_error(3, "must not contain any null bytes");
+		zend_argument_value_error(hostname_argument_offset, "length must be lower than %d", MAX_NAME_LEN);
 		return false;
 	}

 	if (ZSTR_LEN(community) == 0) {
-		zend_argument_must_not_be_empty_error(3);
+		zend_argument_must_not_be_empty_error(hostname_argument_offset + 1);
 		return false;
 	}

@@ -899,14 +890,14 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st
 				char *pport = pptr + 2;
 				tmp_port = atoi(pport);
 				if (tmp_port < 0 || tmp_port > USHRT_MAX) {
-					zend_argument_value_error(2, "remote port must be between 0 and %u", USHRT_MAX);
+					zend_argument_value_error(hostname_argument_offset, "remote port must be between 0 and %u", USHRT_MAX);
 					return false;
 				}
 				remote_port = (unsigned short)tmp_port;
 			}
 			*pptr = '\0';
 		} else {
-			php_error_docref(NULL, E_WARNING, "Malformed IPv6 address, closing square bracket missing");
+			zend_argument_value_error(hostname_argument_offset, "has a malformed IPv6 address, closing square bracket missing");
 			return false;
 		}
 	} else { /* IPv4 address */
@@ -914,7 +905,7 @@ static bool snmp_session_init(php_snmp_session **session_p, int version, zend_st
 			char *pport = pptr + 1;
 			tmp_port = atoi(pport);
 			if (tmp_port < 0 || tmp_port > USHRT_MAX) {
-				zend_argument_value_error(2, "remote port must be between 0 and %u", USHRT_MAX);
+				zend_argument_value_error(hostname_argument_offset, "remote port must be between 0 and %u", USHRT_MAX);
 				return false;
 			}
 			remote_port = (unsigned short)tmp_port;
@@ -1123,14 +1114,13 @@ static ZEND_ATTRIBUTE_NONNULL bool snmp_session_gen_sec_key(struct snmp_session
 /* }}} */

 /* {{{ Set context Engine Id in the snmpv3 session */
-static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string * contextEngineID)
+static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string * contextEngineID, uint32_t contextEngineID_argument_offset)
 {
 	size_t	ebuf_len = 32, eout_len = 0;
 	uint8_t	*ebuf = (uint8_t *) emalloc(ebuf_len);

 	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, ZSTR_VAL(contextEngineID))) {
-		// TODO Promote to Error?
-		php_error_docref(NULL, E_WARNING, "Bad engine ID value '%s'", ZSTR_VAL(contextEngineID));
+		zend_argument_value_error(contextEngineID_argument_offset, "must be a valid context engine ID");
 		efree(ebuf);
 		return false;
 	}
@@ -1145,11 +1135,14 @@ static bool snmp_session_set_contextEngineID(struct snmp_session *s, zend_string
 }
 /* }}} */

-/* {{{ Set all snmpv3-related security options */
+/* {{{ Set all snmpv3-related security options
+ * auth_protocol_argnum and contextEngineID_argument_offset are the userland
+ * argument numbers used for error reporting.
+ */
 static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp_session *session, zend_string *sec_level,
 	zend_string *auth_protocol, zend_string *auth_passphrase, zend_string *priv_protocol,
 	zend_string *priv_passphrase, zend_string *contextName, zend_string *contextEngineID,
-	uint32_t auth_protocol_argnum)
+	uint32_t auth_protocol_argnum, uint32_t contextEngineID_argument_offset)
 {

 	/* Setting the security level. */
@@ -1215,7 +1208,7 @@ static ZEND_ATTRIBUTE_NONNULL_ARGS(2) bool snmp_session_set_security(struct snmp
 	}

 	/* Setting contextEngineIS if specified */
-	if (contextEngineID && ZSTR_LEN(contextEngineID) && !snmp_session_set_contextEngineID(session, contextEngineID)) {
+	if (contextEngineID && ZSTR_LEN(contextEngineID) && !snmp_session_set_contextEngineID(session, contextEngineID, contextEngineID_argument_offset)) {
 		/* Warning message sent already, just bail out */
 		return false;
 	}
@@ -1243,6 +1236,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 	php_snmp_session *session;
 	int session_less_mode = (getThis() == NULL);
 	int timeout_argument_offset = -1;
+	uint32_t oid_argument_offset = 1, type_argument_offset = 0, value_argument_offset = 0;
 	php_snmp_object *snmp_object;
 	php_snmp_object glob_snmp_object;

@@ -1255,8 +1249,8 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 		if (version == SNMP_VERSION_3) {
 			if (st & SNMP_CMD_SET) {
 				ZEND_PARSE_PARAMETERS_START(10, 12)
-					Z_PARAM_STR(a1)
-					Z_PARAM_STR(a2)
+					Z_PARAM_PATH_STR(a1)
+					Z_PARAM_PATH_STR(a2)
 					Z_PARAM_STR(a3)
 					Z_PARAM_STR(a4)
 					Z_PARAM_STR(a5)
@@ -1271,14 +1265,17 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 				ZEND_PARSE_PARAMETERS_END();

 				timeout_argument_offset = 10;
+				oid_argument_offset = 8;
+				type_argument_offset = 9;
+				value_argument_offset = 10;
 			} else {
 				/* SNMP_CMD_GET
 				 * SNMP_CMD_GETNEXT
 				 * SNMP_CMD_WALK
 				 */
 				ZEND_PARSE_PARAMETERS_START(8, 10)
-					Z_PARAM_STR(a1)
-					Z_PARAM_STR(a2)
+					Z_PARAM_PATH_STR(a1)
+					Z_PARAM_PATH_STR(a2)
 					Z_PARAM_STR(a3)
 					Z_PARAM_STR(a4)
 					Z_PARAM_STR(a5)
@@ -1291,12 +1288,13 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 				ZEND_PARSE_PARAMETERS_END();

 				timeout_argument_offset = 9;
+				oid_argument_offset = 8;
 			}
 		} else {
 			if (st & SNMP_CMD_SET) {
 				ZEND_PARSE_PARAMETERS_START(5, 7)
-					Z_PARAM_STR(a1)
-					Z_PARAM_STR(a2)
+					Z_PARAM_PATH_STR(a1)
+					Z_PARAM_PATH_STR(a2)
 					Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str)
 					Z_PARAM_ARRAY_HT_OR_STR(type_ht, type_str)
 					Z_PARAM_ARRAY_HT_OR_STR(value_ht, value_str)
@@ -1306,14 +1304,17 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 				ZEND_PARSE_PARAMETERS_END();

 				timeout_argument_offset = 6;
+				oid_argument_offset = 3;
+				type_argument_offset = 4;
+				value_argument_offset = 5;
 			} else {
 				/* SNMP_CMD_GET
 				 * SNMP_CMD_GETNEXT
 				 * SNMP_CMD_WALK
 				 */
 				ZEND_PARSE_PARAMETERS_START(3, 5)
-					Z_PARAM_STR(a1)
-					Z_PARAM_STR(a2)
+					Z_PARAM_PATH_STR(a1)
+					Z_PARAM_PATH_STR(a2)
 					Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str)
 					Z_PARAM_OPTIONAL
 					Z_PARAM_LONG(timeout)
@@ -1321,6 +1322,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 				ZEND_PARSE_PARAMETERS_END();

 				timeout_argument_offset = 4;
+				oid_argument_offset = 3;
 			}
 		}
 	} else {
@@ -1330,6 +1332,8 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 				Z_PARAM_ARRAY_HT_OR_STR(type_ht, type_str)
 				Z_PARAM_ARRAY_HT_OR_STR(value_ht, value_str)
 			ZEND_PARSE_PARAMETERS_END();
+			type_argument_offset = 2;
+			value_argument_offset = 3;
 		} else if (st & SNMP_CMD_WALK) {
 			ZEND_PARSE_PARAMETERS_START(1, 4)
 				Z_PARAM_ARRAY_HT_OR_STR(oid_ht, oid_str)
@@ -1359,20 +1363,21 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
 		}
 	}

-	if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid_str, oid_ht, type_str, type_ht, value_str, value_ht)) {
+	if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid_str, oid_ht, type_str, type_ht, value_str, value_ht,
+			oid_argument_offset, type_argument_offset, value_argument_offset)) {
 		RETURN_FALSE;
 	}

 	if (session_less_mode) {
-		if (!snmp_session_init(&session, version, a1, a2, timeout, retries, timeout_argument_offset)) {
+		if (!snmp_session_init(&session, version, a1, a2, timeout, retries, 1, timeout_argument_offset)) {
 			php_free_objid_query(&objid_query, oid_ht, value_ht, st);
 			snmp_session_free(&session);
 			RETURN_FALSE;
 		}
-		if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4)) {
+		if (version == SNMP_VERSION_3 && !snmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL, 4, 0)) {
 			php_free_objid_query(&objid_query, oid_ht, value_ht, st);
 			snmp_session_free(&session);
-			/* Warning message sent already, just bail out */
+			/* An error has already been emitted, just bail out. */
 			RETURN_FALSE;
 		}
 	} else {
@@ -1645,7 +1650,7 @@ PHP_METHOD(SNMP, __construct)

 	snmp_object = Z_SNMP_P(object);

-	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lSS|ll", &version, &a1, &a2, &timeout, &retries) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lPP|ll", &version, &a1, &a2, &timeout, &retries) == FAILURE) {
 		RETURN_THROWS();
 	}

@@ -1664,7 +1669,7 @@ PHP_METHOD(SNMP, __construct)
 		snmp_session_free(&(snmp_object->session));
 	}

-	if (!snmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries, 4)) {
+	if (!snmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries, 2, 4)) {
 		return;
 	}
 	snmp_object->max_oids = 0;
@@ -1738,8 +1743,9 @@ PHP_METHOD(SNMP, setSecurity)
 		RETURN_THROWS();
 	}

-	if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2)) {
-		/* Warning message sent already, just bail out */
+	/* authProtocol is argument #2 and contextEngineId is argument #7. */
+	if (!snmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7, 2, 7)) {
+		/* An error has already been emitted, just bail out. */
 		RETURN_FALSE;
 	}
 	RETURN_TRUE;
diff --git a/ext/snmp/tests/gh16959.phpt b/ext/snmp/tests/gh16959.phpt
index cabe0eb84b6..f76fa61e1f7 100644
--- a/ext/snmp/tests/gh16959.phpt
+++ b/ext/snmp/tests/gh16959.phpt
@@ -66,5 +66,5 @@
 }
 Object of class stdClass could not be converted to string
 Object of class stdClass could not be converted to string
-Type must be a single character
-Type must be a single character
+snmp2_set(): Argument #4 ($type) must be a single character
+snmp2_set(): Argument #4 ($type) must be a single character
diff --git a/ext/snmp/tests/ipv6.phpt b/ext/snmp/tests/ipv6.phpt
index c305fb15d4b..93274fd7054 100644
--- a/ext/snmp/tests/ipv6.phpt
+++ b/ext/snmp/tests/ipv6.phpt
@@ -22,10 +22,12 @@
 snmp_set_valueretrieval(SNMP_VALUE_PLAIN);

 var_dump(snmpget($hostname6_port, $community, '.1.3.6.1.2.1.1.1.0'));
-var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0'));
+try {
+    var_dump(snmpget('[dead:beef::', $community, '.1.3.6.1.2.1.1.1.0'));
+} catch (\ValueError $e) {
+    echo $e->getMessage() . \PHP_EOL;
+}
 ?>
 --EXPECTF--
 string(%d) "%s"
-
-Warning: snmpget(): Malformed IPv6 address, closing square bracket missing in %s on line %d
-bool(false)
+snmpget(): Argument #1 ($hostname) has a malformed IPv6 address, closing square bracket missing
diff --git a/ext/snmp/tests/snmp-object-setSecurity_error.phpt b/ext/snmp/tests/snmp-object-setSecurity_error.phpt
index cf4f9288377..576ec838080 100644
--- a/ext/snmp/tests/snmp-object-setSecurity_error.phpt
+++ b/ext/snmp/tests/snmp-object-setSecurity_error.phpt
@@ -53,7 +53,11 @@

 var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', ''));
 var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'ty'));
-var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa'));
+try {
+    var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa'));
+} catch (\ValueError $e) {
+    echo $e->getMessage() . \PHP_EOL;
+}

 var_dump($session->close());

@@ -76,7 +80,5 @@

 Warning: SNMP::setSecurity(): Error generating a key for privacy pass phrase 'ty': Generic error (The supplied password length is too short.) in %s on line %d
 bool(false)
-
-Warning: SNMP::setSecurity(): Bad engine ID value 'dsa' in %s on line %d
-bool(false)
+SNMP::setSecurity(): Argument #7 ($contextEngineId) must be a valid context engine ID
 bool(true)
diff --git a/ext/snmp/tests/snmp2_get.phpt b/ext/snmp/tests/snmp2_get.phpt
index 30500eb5ca9..e2cd1ef1b45 100644
--- a/ext/snmp/tests/snmp2_get.phpt
+++ b/ext/snmp/tests/snmp2_get.phpt
@@ -54,7 +54,7 @@
 --EXPECTF--
 Checking error handling
 Empty OID array
-Array of object IDs must not be empty
+snmp2_get(): Argument #3 ($object_id) must not be empty when passed as an array
 Checking working
 Single OID
 string(%d) "%s"
diff --git a/ext/snmp/tests/snmp2_set.phpt b/ext/snmp/tests/snmp2_set.phpt
index 11b1d94419f..da94fe21f49 100644
--- a/ext/snmp/tests/snmp2_set.phpt
+++ b/ext/snmp/tests/snmp2_set.phpt
@@ -128,14 +128,22 @@
 var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

 echo "Multiple OID, single type in array, multiple value\n";
-$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
-var_dump($z);
+try {
+    $z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
+    var_dump($z);
+} catch (\ValueError $e) {
+    echo $e->getMessage() . \PHP_EOL;
+}
 var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
 var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

 echo "Multiple OID & type, single value in array\n";
-$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
-var_dump($z);
+try {
+    $z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
+    var_dump($z);
+} catch (\ValueError $e) {
+    echo $e->getMessage() . \PHP_EOL;
+}
 var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
 var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

@@ -167,7 +175,7 @@
 --EXPECTF--
 Check error handing
 No type & no value (timeout & retries instead)
-Type must be a single character
+snmp2_set(): Argument #4 ($type) must be a single character
 No value (timeout instead), retries instead of timeout

 Warning: snmp2_set(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d
@@ -216,23 +224,19 @@
 bool(true)
 bool(true)
 Multiple OID, 1st wrong type
-Type must be a single character
+snmp2_set(): Argument #4 ($type) must be a single character
 bool(true)
 bool(true)
 Multiple OID, 2nd wrong type
-Type must be a single character
+snmp2_set(): Argument #4 ($type) must be a single character
 bool(true)
 bool(true)
 Multiple OID, single type in array, multiple value
-
-Warning: snmp2_set(): '%s': no type set in %s on line %d
-bool(false)
+snmp2_set(): Argument #4 ($type) must contain a type for object ID 'SNMPv2-MIB::sysLocation.0'
 bool(true)
 bool(true)
 Multiple OID & type, single value in array
-
-Warning: snmp2_set(): '%s': no value set in %s on line %d
-bool(false)
+snmp2_set(): Argument #5 ($value) must contain a value for object ID 'SNMPv2-MIB::sysLocation.0'
 bool(true)
 bool(true)
 Multiple OID, 1st bogus, single type, multiple value
diff --git a/ext/snmp/tests/snmpset.phpt b/ext/snmp/tests/snmpset.phpt
index ca935cecf5e..a4f89e78da9 100644
--- a/ext/snmp/tests/snmpset.phpt
+++ b/ext/snmp/tests/snmpset.phpt
@@ -122,14 +122,22 @@
 var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

 echo "Multiple OID, single type in array, multiple value\n";
-$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
-var_dump($z);
+try {
+    $z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
+    var_dump($z);
+} catch (\ValueError $e) {
+    echo $e->getMessage() . \PHP_EOL;
+}
 var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
 var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

 echo "Multiple OID & type, single value in array\n";
-$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
-var_dump($z);
+try {
+    $z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
+    var_dump($z);
+} catch (\ValueError $e) {
+    echo $e->getMessage() . \PHP_EOL;
+}
 var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
 var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));

@@ -161,7 +169,7 @@
 --EXPECTF--
 Check error handing
 No type & no value (timeout & retries instead)
-Type must be a single character
+snmpset(): Argument #4 ($type) must be a single character
 No value (timeout instead), retries instead of timeout

 Warning: snmpset(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d
@@ -207,23 +215,19 @@
 bool(true)
 bool(true)
 Multiple OID, 1st wrong type
-Type must be a single character
+snmpset(): Argument #4 ($type) must be a single character
 bool(true)
 bool(true)
 Multiple OID, 2nd wrong type
-Type must be a single character
+snmpset(): Argument #4 ($type) must be a single character
 bool(true)
 bool(true)
 Multiple OID, single type in array, multiple value
-
-Warning: snmpset(): '%s': no type set in %s on line %d
-bool(false)
+snmpset(): Argument #4 ($type) must contain a type for object ID 'SNMPv2-MIB::sysLocation.0'
 bool(true)
 bool(true)
 Multiple OID & type, single value in array
-
-Warning: snmpset(): '%s': no value set in %s on line %d
-bool(false)
+snmpset(): Argument #5 ($value) must contain a value for object ID 'SNMPv2-MIB::sysLocation.0'
 bool(true)
 bool(true)
 Multiple OID, 1st bogus, single type, multiple value