andrew has asked for the wisdom of the Perl Monks concerning the following question:

I recieve this error..
called with 3 bind variables when 2 are needed at index.cgi line 786.
from this code...
$sth = $dbh->prepare("INSERT INTO wbwc_roster(member, group, o +rg) VALUES (?, ?, '$org')"); $sth->execute(param("member"), param("group")) or die $dbh-> +errstr;

Replies are listed 'Best First'.
Re: MySQL confusion (security hole?)
by Ovid (Cardinal) on Sep 11, 2002 at 22:09 UTC

    The CGI::param function relies on wantarray to determine the context in which it is called. In your execute statement, it's being called in list context and if either "member" or "goup" can return more than one value, they will. Further, just adding this data to the database without sanity checking is not a good idea. Who knows what values might get in their and whether or not they are correct? Also, you may as well pass $org in as a bind variable. It's more consistent.

    Assuming that you have already untainted $org and that "member" and "group" are numeric only (just assuming for illustrative purposes, of course):

    my $_member = param( 'member' ); my $_group = param( 'group' ); # untaint #(this was wrong at first. Thanks to tye for catching my stupid err +or) :( my ( $member ) = $_member =~ /^(\d+)$/; my ( $group ) = $_group =~ /^(\d+)$/; my $sql = 'INSERT INTO wbwc_roster(member, group, org) VALUES (?, ?, + ?)'; my $sth = $dbh->prepare( $sql ); $sth->execute( $member, $group, $org ) or die $dbh->errstr;

    Something along those lines should solve the problem. However, if either "member" or "group" do legitimately have more than one value, you're losing information.

    Cheers,
    Ovid

    Update: I think I should clarify about the potential security issue here. Let's say your group table is defined like this:

    group_id | group_name --------------------- 1 | admin 2 | programmer 3 | quality control 4 | manager

    Now let's say that someone on your system can add people to your roster, but isn't allowed to add them to the admin group unless they are already an administrator. Even if the Web page they submit doesn't give them an "admin" group, it's trivial to munge the results to submit a "1" as the group id. Thus, someone can escalate priveleges of the person added to the roster. This may not apply in your case, but it's worth considering. You may need to add much more sanity checking to your code.

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

(tye)Re: MySQL confusion
by tye (Sage) on Sep 11, 2002 at 22:05 UTC

    If you have &member=me&member=you then CGI.pm's param("member") would return ("me","you") which could explain what you are noticing. param("member") could also return 0 items and give you the opposite error.

    You might try (param("member"))[-1] so that only the last one specified is used. But, for some reason, (emptyList)[-1] is an empty list (I expected it to be undef), so to be extra safe use:

    my $member= (param("member"))[-1]; my $group= (param("group"))[-1]; $sth->execute( $member, $group ) ...
    perhaps with some extra safety checks thrown in.

    You could also use scalar or ''.param("member") to work around the problem (plus lots of other possiblities), but I like those solutions less.

            - tye (but my friends call me "Tye")
Re: MySQL confusion
by dws (Chancellor) on Sep 11, 2002 at 21:59 UTC
    called with 3 bind variables when 2 are needed at index.cgi line 786.

    $sth->execute(param("member"), param("group"))

    Just a guess: Could one of those input parameters be multi-valued? If so, you'll need to flatten it and extra the (single) value you want to pass to the query.

Re: MySQL confusion
by andrew (Acolyte) on Sep 11, 2002 at 22:27 UTC
    You have an error in your SQL syntax near 'group, org) VALUES ('_PiNa_ +CaLaDa_', '10', 1)' at line 1 at index.cgi line 789
    Iget that error now
Re: MySQL confusion
by andrew (Acolyte) on Sep 11, 2002 at 22:17 UTC
    oh I have two members lol, thanks I didntknow that would give a error