PerlDancer / PerlDancer/Dancer2

params('body') dies with 'Not a HASH reference' on a JSON array body

Open Beginner friendly
#1,814 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug
Dominant language
Perl
Stars
604
Forks
288
Avg merge
1d 5h
Merged PRs (30d)
5

Description

Status: confirmed against main @ 21bc21d9

lib/Dancer2/Core/Request.pm:351:

return %{ $self->_body_params || {} } if wantarray;

The || {} guards undef but not a non-hash reference. deserialize (line 238) assigns whatever the serializer returned straight into _body_params, and a JSON array or bare scalar body is perfectly legal JSON.

Reproduction

perl -Ilib -e 'use Dancer2::Serializer::JSON; use Dancer2::Core::Request;
  open my $fh, "<", \q{[1,2,3]};
  my $r = Dancer2::Core::Request->new(serializer=>Dancer2::Serializer::JSON->new,
    env=>{REQUEST_METHOD=>"POST",PATH_INFO=>"/",QUERY_STRING=>"",CONTENT_TYPE=>"application/json",
      CONTENT_LENGTH=>7,"psgi.input"=>$fh,"psgi.url_scheme"=>"http",SERVER_NAME=>"l",SERVER_PORT=>80});
  my @p = eval { $r->params("body") }; print $@ ? "DIED: $@" : "ok\n"'
DIED: Not a HASH reference at lib/Dancer2/Core/Request.pm line 351.

Impact

Any application calling params('body') in list context can be 500'd by an unauthenticated request with a JSON array body.

Suggested fix

elsif ( $source eq 'body' ) {
    my $p = $self->_body_params;
    return ( is_hashref($p) ? %{$p} : () ) if wantarray;
    return $p;
}

is_hashref is already imported at line 14. Apply the same guard to the query branch for symmetry.

Worth deciding explicitly: whether returning the raw non-hash value in scalar context is the right contract, or whether it should be undef. body_data (line 690) has its own opinion about this, and the two should agree.

Suggested test

A JSON body of [1,2,3] does not 500 via params('body') in list context.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/Dancer2/Core/Request.pm at params around line 351 and deserialize around line 238, then compare body_data around line 690. Reproduce with the provided JSON array request and add a regression test showing params('body') in list context does not die. Done when the non-hash body behavior is consistent with the chosen scalar-context contract and the regression passes.

Written by the indexing model from the issue text.

Assessment

Tech stack
perl
Domain
api, backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.