InvalidArgumentException: Invalid string IP

Rasmus Vind

Well-known member
Licensed customer
Affected version
2.3.9
Summary
XF\Job\ApprovalQueueProcess crashes with InvalidArgumentException: Invalid string IP when the moderator log entry is created from CLI.

Reproduce
  1. Have content (e.g. a post) sitting in the approval queue.
  2. A moderator approves it through the UI, which enqueues an ApprovalQueueProcess job rather than acting inline.
  3. The job is later picked up by the CLI runner (php cmd.php xf:run-jobs, or the system cron).

What happens
XF\ModeratorLog\AbstractHandler::setupLogEntityActor() sees $actor->user_id == \XF::visitor()->user_id (because ApprovalQueueProcess::run() wraps the action in \XF::asVisitor($asUser, …)) and calls:

Code:
$log->ip_address = Ip::stringToBinary(\XF::app()->request()->getIp());

In CLI context $_SERVER['REMOTE_ADDR'] is unset, so Request::getIp() returns an empty string and Ip::stringToBinary('') throws.

Stack trace
Code:
  InvalidArgumentException: Invalid string IP: src/XF/Util/Ip.php:17

  #0 src/XF/ModeratorLog/AbstractHandler.php(137): XF\Util\Ip::stringToBinary('')
  #1 src/XF/ModeratorLog/AbstractHandler.php(118): XF\ModeratorLog\AbstractHandler->setupLogEntityActor(...)
  #2 src/XF/ModeratorLog/AbstractHandler.php(92):  XF\ModeratorLog\AbstractHandler->log(...)
  #3 src/XF/ModeratorLog/Logger.php(79):           XF\ModeratorLog\Logger->logChanges('post', ...)
  #4 src/XF/Logger.php(49):                        XF\Logger->logModeratorChanges('post', ...)
  #5 src/XF/Entity/Post.php(626):                  XF\Entity\Post->_postSave()
  #9 src/XF/Service/Post/ApproverService.php(39):  XF\Mvc\Entity\Entity->save()
  #10 src/XF/ApprovalQueue/PostHandler.php(30):    XF\Service\Post\ApproverService->approve()
  #11 src/XF/ApprovalQueue/AbstractHandler.php(202): XF\ApprovalQueue\PostHandler->actionApprove(...)
  #12 src/XF/Job/ApprovalQueueProcess.php(71):     XF\ApprovalQueue\AbstractHandler->performAction('approve', ...)
  #13 src/XF.php(914):                             XF\Job\ApprovalQueueProcess->XF\Job\{closure}()
  #14 src/XF/Job/ApprovalQueueProcess.php(57):     XF::asVisitor(..., Closure)
  #15 src/XF/Job/Manager.php(275):                 XF\Job\ApprovalQueueProcess->run(8)
  …
  #18 src/XF/Cli/Command/RunJobs.php(58):          XF\Job\Manager->runJobEntry(...)

Suggested fix
Skip the IP assignment when there isn't a real request IP available, e.g.:
Code:
protected function setupLogEntityActor(ModeratorLog $log, User $actor)
  {
      $log->user_id = $actor->user_id ?? 0;

      if ($actor->user_id == \XF::visitor()->user_id)
      {
          $ip = \XF::app()->request()->getIp();
          if ($ip !== '')
          {
              $log->ip_address = Ip::stringToBinary($ip);
          }
      }
  }
xf_moderator_log.ip_address is already nullable/blob, so leaving it empty for CLI-originated log rows is consistent with other "no request" code paths.
 
Back
Top Bottom