Menu

#1847 bug in expr error handler

obsolete: 8.4a5
closed-fixed
5
2002-04-18
2002-04-11
Anonymous
No

% set begin 6658020034
6658020034
% set end 658020034
658020034
% expr abs($end - $begin)
integer value too large to represent
% expr { abs($end - $begin) }
can't use floating-point value as operand of "-"
% expr { abs(658020034 - 6658020034) }
integer value too large to represent

Can someone explain where Tcl thinks the floating
point value is? And why is a floating point value
not a valid operand of "-"?

- Phil Ehrens

This is just an example of too much sharing of a
common routine for producing an error message.

There's one routine for generating the "illegal
operand" error message, and by the time it is called,
the context isn't around any more to tailor the
message precisely. So the error message generator
knows that "658020034" was "bad", and it can see that
that is a legal floating-point value, so it assumes
that the error is that a floating-point value was used
where it should not be. Go ahead and file a bug report
under the "ByteCode Compiler" Category.

- Don Porter

Discussion

  • miguel sofer

    miguel sofer - 2002-04-15

    Logged In: YES
    user_id=148712

    Note that this particular example fails to produce the error
    in tcl8.5 (Donal's 64 bit arithmetic), but it can be
    reproduced by going beyong the 64-bit limit:
    set begin 665802003400000000000000

     
  • miguel sofer

    miguel sofer - 2002-04-15
    • milestone: 155785 --> obsolete: 8.4a5
     
  • miguel sofer

    miguel sofer - 2002-04-15

    Logged In: YES
    user_id=148712

    Note that 'abs' has nothing to do with it

    % set begin 665802003400000000000000
    665802003400000000000000
    % expr $begin - 1
    integer value too large to represent
    % expr {$begin - 1}
    can't use floating-point value as operand of "-"

     
  • miguel sofer

    miguel sofer - 2002-04-16

    Logged In: YES
    user_id=148712

    Related bug (the relationship is in the cause, not the symptom):

    % set begin 665802003400000000000000
    665802003400000000000000
    % expr {1 && $begin}
    1
    % expr 1 && $begin
    integer value too large to represent

     
  • miguel sofer

    miguel sofer - 2002-04-16

    Logged In: YES
    user_id=148712

    Another sibling is

    % set a 08
    08
    % expr $a+1
    "08" is an invalid octal number
    % expr {$a+1}
    can't use invalid octal number as operand of "+"

     
  • miguel sofer

    miguel sofer - 2002-04-16

    Logged In: YES
    user_id=148712

    More ...

    % set a 08
    08
    % expr abs($a)
    "08" is an invalid octal number
    % expr {abs($a)}
    argument to math function was an invalid octal number

    The error cases follow a different path, and produce
    different results.In this particular case, I like the second
    one better ...

     
  • Andreas Kupries

    Andreas Kupries - 2002-04-16

    Logged In: YES
    user_id=75003

    Why is that a sibling ?

    The leading 0 tells tcl to interpret 08 as an octal number,
    but 8 is not a valid octal digit, Hence it is an invalid
    octal number, and the message is essentially correct in
    both cases. Or is the problem that the message is different
    for the two cases ?

     
  • miguel sofer

    miguel sofer - 2002-04-16

    Logged In: YES
    user_id=148712

    Yes, in my mind (and in the evolving patch), the problem to
    fix is "both paths should produce the same error messages,
    but don't". All of these fall in *that* category, although
    some are less severe as they produce different but correct
    messages. Maybe it is not necessary to produce the same
    error message,as long as it is a correct one?

     
  • Andreas Kupries

    Andreas Kupries - 2002-04-16

    Logged In: YES
    user_id=75003

    Ok. I also prefer that the path should produce the same
    message. If that is not possible I am willing to settle for
    different yet correct messages.

     
  • miguel sofer

    miguel sofer - 2002-04-16

    Logged In: YES
    user_id=148712

    Are these bugs too?

    % set a 08
    08
    % expr $a
    "08" is an invalid octal number
    % expr {$a}
    08
    % set b 665802003400000000000000
    665802003400000000000000
    % expr $b
    integer value too large to represent
    % expr {$b}
    665802003400000000000000

     
  • Jeffrey Hobbs

    Jeffrey Hobbs - 2002-04-16

    Logged In: YES
    user_id=72656

    No, those are being treated as normal strings. That has
    always been a behavior of expr.

     
  • miguel sofer

    miguel sofer - 2002-04-17

    Logged In: YES
    user_id=148712

    According to expr.n:
    "If no numeric interpretation is possible, then an operand
    is left as a string (and only a limited set of operators
    may be applied to it)."

    As I understand that, the following is indeed a bug:

    % set a 08
    08
    % expr $a
    "08" is an invalid octal number
    % expr 08
    "08" is an invalid octal number

    The source of misunderstanding is obviously in "no numeric
    representation is possible": tcl seems to say that "08" can
    be represented as a number, which happens to be invalid -
    I'd rather say that 08 cannot be represented as a number.

    In the same vein, how should we interpret a string of digits
    that is too large to represent as an integer: "an integer
    too large to represent", or "a string that cannot be
    represented as a number"?

     
  • Jeffrey Hobbs

    Jeffrey Hobbs - 2002-04-17

    Logged In: YES
    user_id=72656

    I don't think you are reading the docs right (or they
    aren't written clearly). 'expr foo' fails as well, but
    expr {"foo"} and expr {"08"} are both OK.

     
  • Nobody/Anonymous

    Logged In: NO

    Boy, if I went so far off-topic in one of my bug reports
    here I would be flayed alive.

    The problem, whatever caused it, is that the error message
    reported per my original bug report is wrong by anybody's
    measure of wrongness... except possibly Ariel Sharon,
    whose measure seems to have a directional component which
    makes it unreliable.

     
  • miguel sofer

    miguel sofer - 2002-04-17

    Logged In: YES
    user_id=148712

    Indeed; the cause of the bug is that the error handler for
    operations in the bc engine (IllegalExprOperandType) assumes
    that it can only get empty strings, bad octals or (default)
    floating point values. So, a superficial fix just touches that.

    The issue that is worrying me is: is this really a "bad
    operand" issue, or should the error have been caught
    earlier? As there are two different execution paths for
    [expr] (braced vs unbraced), and they seem to behave
    differently ...

    Anyway, I'll fix the immediate issue and log a new bug
    report with the deeper one. Sorry for messing up the discussion.

     
  • Jeffrey Hobbs

    Jeffrey Hobbs - 2002-04-17

    Logged In: YES
    user_id=72656

    I believe the reason that the compiled object version fails
    with a different message is that it will first try and get
    it with GetIntFromObj, which fails. It then tries
    GetDoubleFromObj, which succeeds (because strtod has larger
    range acceptance), but then fails as doubles (floats)
    aren't accepted for abs.

    In the static case, it fails because it succeeds the
    LooksLikeInt, which means it is either an acceptable int or
    one too large to represent.

    Quite simple, no?

    In the first case, it's Tcl that sub's end and begin, not
    the expr parser, so you get the too large int again.

     
  • miguel sofer

    miguel sofer - 2002-04-17

    Logged In: YES
    user_id=148712

    No, it never gets to 'abs'; note that it is '-' complaining
    about a non valid operand. Doubles are acceptable operands
    for 'abs'.

    Look at what is happening in INST_SUB: TclLooksLikeInt
    returns 1, so GetIntFromObj is called and it fails, so that
    IllegalExprOperandType gets called. GetDoubleFromObj is
    never called (it is called only when TclLooksLikeInt fails).

    The problem is indeed that IllegalExprOperandType is not
    expecting to receive "too large integers". The local fix
    there will produce something like

    % expr { abs($end - $begin) }
    can't use integer value too large to represent as operand of
    "-"

    The case

    % expr abs($end - $begin)
    integer value too large to represent

    is caught earlier, before subtraction is ever attempted.

     
  • Donal K. Fellows

    Logged In: YES
    user_id=79902

    Problem is really that GET_WIDE_OR_INT (really just
    Tcl_Get(Wide)IntFromObj) is failing due to integer range
    overflow, and the code as it stands does not check for that
    error case. However, you can't always feed the value to
    parse into Tcl_GetDoubleFromObj when GET_WIDE_OR_INT fails
    due to things like invalid octal. What's worse, the nature
    of the failure has vanished at this point because
    GET_WIDE_OR_INT does not use an interpreter, and
    Tcl_Get(Wide)IntFromObj resets errno... :^(

     
  • miguel sofer

    miguel sofer - 2002-04-18
     
  • miguel sofer

    miguel sofer - 2002-04-18

    Logged In: YES
    user_id=148712

    Enclosing a patch for tcl8.3 sources that fixes the
    immediate issue.

     
  • miguel sofer

    miguel sofer - 2002-04-18

    Logged In: YES
    user_id=148712

    Patch for tcl8.4 attached; committed to both HEAD and
    core-8-3-1-branch.

    The initial issue is solved; bug report #545661 was opened
    for the dependence of [expr]'s error handling on the timeof
    compilation.

     
  • miguel sofer

    miguel sofer - 2002-04-18
     
  • miguel sofer

    miguel sofer - 2002-04-18
    • status: open --> closed-fixed