8

in system.sysutils.pas, in Rio they add this instruction:

var intPart: String;

... IntPart.Chars[length(IntPart)] in ['1','3','5','7','9'] ...

But as far as i know, s.Chars[xx] will be always zero-based string so doing IntPart.Chars[length(IntPart)] in ['1','3','5','7','9'] will always go out of the boundary ?

it's must not be written instead

... IntPart.Chars[length(IntPart)-1] in ['1','3','5','7','9'] ...

Or I miss something ?

zeus
  • 9,795
  • 5
  • 45
  • 112
  • one last byte for null terminated strings? (just a first guess) – Nasreddine Galfout Apr 30 '19 at 11:54
  • 1
    @NasreddineGalfout no IntPart is a String and anyway why comparing a #0 in ['1','3','5','7','9'] .... – zeus Apr 30 '19 at 11:58
  • 4
    Yes, the `String.Chars[]` operates on a zero-based string. See [SysUtils.TStringHelper.Chars](http://docwiki.embarcadero.com/Libraries/en/System.SysUtils.TStringHelper.Chars). The code in question should have used `Length(intPart)-1` to get the last character in the string. Setting range checking on, does however not raise an exception. – LU RD Apr 30 '19 at 13:10
  • 3
    So you found two bugs, the invalid check of the last character in `SysUtils.InternalTextToCurrency`, and the missing range check in `TStringHelper.Chars`. – LU RD Apr 30 '19 at 13:24
  • @LURD: There are no zero based strings. The strings are always the same, but not the index values. The indexing of the Chars array property is however **always** zero based, regardless of the $ZEROBASEDSTRINGS settings. I agree with the rest: there is no range checking even if there should be and the index is off by one. – Rudy Velthuis Apr 30 '19 at 14:41
  • @RudyVelthuis, I think you are splitting hairs now. From docs about TStringHelper.Chars: `Accesses individual characters in this zero-based string.` It is well known that `TStringHelper` are written to always operate on ZBS strings, regardless of compiler settings. – LU RD Apr 30 '19 at 15:13
  • 1
    The docs are wrong too. Again: **there are no zero-based strings**, only the way they are indexed is different. The **same** string can be indexed zero-based or one-based, depending on the settings. TStringHelper is not written to operate on zero-based strings. It uses zero-based indexes. TStringHelper can operate on any UnicodeString, no matter which settings are used and will always present a zero-based interface to the string. – Rudy Velthuis Apr 30 '19 at 15:28
  • 2
    Apart from discussing here about how many angels can dance on a pin point: Is anybody going to file a bug report on this? – dummzeuch Apr 30 '19 at 15:43
  • @dummzeuch, I'm working on it. (As a fellow german coworker once said: I'm hardly working on it!) See [TStringHelper.Chars does not issue a range error when index is out of bounds](https://quality.embarcadero.com/browse/RSP-24360) for starters. – LU RD Apr 30 '19 at 17:06
  • @dummzeuch, updated answer with QP references. – LU RD Apr 30 '19 at 17:34
  • @Rudy The docs aren't wrong because they chose to express things in different terms from how you would express them. You just have to read them with a little empathy. – David Heffernan Apr 30 '19 at 22:20
  • The strings are not zero based, so if the docs say so, they are wrong. The **exact identical** string can be accessed in a zero-based and in a one-based manner. That has nothing to do with empathy (empathy for a document, really?). – Rudy Velthuis Apr 30 '19 at 23:46
  • @dummzeuch: That is not academic or irrelevant ("angels on a pin point"). The terminology is wrong and that is why so many people actually misunderstand the entire "problem". Quite a few of them don't know that it is just how strings are indexed, they think the strings are different and incompatible. – Rudy Velthuis Apr 30 '19 at 23:50

1 Answers1

10

But as far as i know, s.Chars[xx] will be always zero-based string

Yes, the TStringHelper routines are written to operate on strings as zero based, regardless of the compiler settings ({$ZEROBASEDSTRINGS ON/OFF}). See SysUtils.TStringHelper.Chars.

so doing IntPart.Chars[length(IntPart)] in ['1','3','5','7','9'] will always go out of the boundary ?

That is correct. It should have been Length(IntPart)-1.

Reported as: SysUtils.InternalTextToCurrency accesses a string out of bounds

Update: Fixed in Delphi 10.3.3 Rio.


Furthermore, when range check is on, IntPart.Chars[length(IntPart)] should have raised an exception. This is also bug (in TStringHelpers.Chars).

Reported as: TStringHelper.Chars does not issue a range error when index is out of bounds

LU RD
  • 32,988
  • 5
  • 71
  • 260