php pack(“H*, $s) does not throw exception or return false on error. SOLVED.

I was puzzled by this recently, code that uses pack(“H*”, $s) to compress a token into a few bytes would cause a warning to be displayed by php if the $s token was not a valid hexadecimal string, but still return a bogus result.  try { $p = pack(“H*”, $s); } catch (Exception $e) { } would not catch it, as it is emitted as a warning, not an error.

The warning looks like this:

pack(): Type H: illegal hex digit s in /my/fancy/webapp/problem.php on line 123

After a bunch of unsuccessful googling somebody from effnet reminded me to look up error handling specifics, but  all I  found was how to create error handlers that could catch that sort of thing. But I don’t want to introduce an error handler just yet, instead I am trying to find a simple way to detect failure of the function pack(), i.e. a way to query the error status, so I started experimenting with error_get_last() and came up with the following:

  1. <?php
  2.         function attemptpack($s) {
  3.                 @trigger_error(“”);
  4.                 $p=pack(“H*”, $s);
  5.                 $e = error_get_last();
  6.                 if ($e && !(strpos($e[“message”], “pack()”) === FALSE)) {
  7.                         print(“$s pack error detected:” . $e[“message”] . “\n”);
  8.                 }  else {
  9.                         print “$s packed ok\n”;
  10.                 }
  11.         }
  12.         attemptpack(“abcdef”);
  13.         attemptpack(“axbcdef”);
  14.         attemptpack(“abcdef”);
  15. ?>

Note I am paranoid and am verifying that the message contains pack() in case an older message was not cleared by @trigger. It should not be necessary at this point.

Turns out that does not work on php 5.1.6. And the more obvious way to do this is to validate the input anyways. So now my approach is now much more simple:

  1. <?php
  2. function attemptpack($s) {
  3.     if ( !ctype_xdigit($s))  {
  4.         print __FILE__ . “: $s is not a valid hex string.\n”;
  5.     } else {
  6.         $p=pack(“H*”, $s);
  7.     }
  8. }
  9. attemptpack(“abcdef”);
  10. attemptpack(“abxdef”);
  11. ?>