php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #41375 substr() undocumented behavior change from 5.2.1 to 5.2.2
Submitted: 2007-05-12 12:52 UTC Modified: 2007-09-07 18:05 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: bugs dot php dot net at kreidenweis dot com Assigned:
Status: Not a bug Package: Documentation problem
PHP Version: 5.2.2 OS: Any
Private report: No CVE-ID: None
 [2007-05-12 12:52 UTC] bugs dot php dot net at kreidenweis dot com
Description:
------------
substr() handled a negative $start parameter with an absolute value larger than the $string's length gracefully and sensibly up to PHP 5.2.1

In 5.2.2 this behavior changed without that being mentioned in the documentation.

IMHO it probably has something to do with the fix for http://bugs.php.net/bug.php?id=40754

I guess (and hope ;) the behavior change wasn't intended. But if indeed so, please put a warning in the documentation.

Reproduce code:
---------------
var_dump(substr('abc', -4));

Expected result:
----------------
string(3) "abc"

(up to PHP 5.2.1 this is what happens)

Actual result:
--------------
bool(false)

(output by PHP 5.2.2)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-05-12 15:47 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

.
 [2007-09-07 02:20 UTC] chagenbu@php.net
I'm sorry, but this is a definite BC break and has bitten me both in Horde code and in my company's codebase. I've re-read the substr docs several times and I don't see any indication that a negative $start can cause substr to return false. Here's the description of the start parameter in its entirety:

If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth.

If start is negative, the returned string will start at the start'th character from the end of string.

Example 2454. Using a negative start
<?php
$rest = substr("abcdef", -1);    // returns "f"
$rest = substr("abcdef", -2);    // returns "ef"
$rest = substr("abcdef", -3, 1); // returns "d"

... from http://us3.php.net/substr.
 [2007-09-07 02:22 UTC] chagenbu@php.net
Seems to me as if this was introduced with 5.2.3, not 5.2.2 per the original submitter. Also see http://us.php.net/manual/en/function.substr.php#75999 - this isn't something that only affects me.
 [2007-09-07 06:48 UTC] pajoye@php.net
"If start is negative, the returned string will start at the start'th
character from the end of string."

The function still accepts a negative start. What changed is if the start is longer than the string length, the test (user friendly version):

 if (from > strlen(str) || (from < 0 && -from > strlen(str)))

As I agree it may break some scripts, the new behavior should be documented, as a bug fix.

Can we move this bug to the doc category?
 [2007-09-07 09:40 UTC] jani@php.net
Reclassified.

 [2007-09-07 14:46 UTC] chagenbu@php.net
Okay, documenting it at least makes code and documentation consistent, but why the change in the first place? Why not avoid the break and leave it consistent?
 [2007-09-07 14:59 UTC] tony2001@php.net
Don't you think such questions should have been asked during RC stage?
It's a bit too late to change it back, what's done is done.
 [2007-09-07 15:12 UTC] chagenbu@php.net
Yes, of course it should have been caught in the RC stage, but it wasn't - in fact it took me more than one final release to track it down.

Why is what's done, done, when the behavior that was changed existed for years and years, and the new behavior has been around for 2 point releases?
 [2007-09-07 15:36 UTC] tony2001@php.net
I don't think it's good idea to change it in every release back and forth.
Also the current behavior makes much more sense to me.
Negative string length is a nonsense, so false is the correct result.
 [2007-09-07 15:50 UTC] chagenbu@php.net
Alright, here's the use case:

I have a string. I want at most 16 characters of it. For all PHP versions before 5.2.[2 or 3], I could do this:

$shorter = substr($string, -16);

Now I have to do this:

if (strlen($string) > 16))
    $shorter = substr($string, -16);
else
    $shorter = $string;


My question is, especially since I'm asking that the historical behavior of PHP be maintained, how does this change improve the language? What is the point of it?
 [2007-09-07 16:10 UTC] tony2001@php.net
>if (strlen($string) > 16))
>    $shorter = substr($string, -16);
>else
>    $shorter = $string;

$shorter = substr($string, 0, 16);
Please don't tell me you didn't know that.
 [2007-09-07 17:25 UTC] chagenbu@php.net
I should have specified that sometimes you only want the last X characters of a string. That's what this is about.
 [2007-09-07 17:46 UTC] sean@php.net
As far as I can tell, this has been documented since at least 2002. The fact that it worked up until 5.2.1 doesn't mean that you should have used it.

From the docs:
"""If string is less than or equal to start characters long, FALSE  will be returned."""

http://cvs.php.net/viewvc.cgi/phpdoc/en/reference/strings/functions/substr.xml?revision=1.1&view=markup

S
 [2007-09-07 18:05 UTC] chagenbu@php.net
Ah. I do see that now, but it's in the docs for when $length is given and is positive. I guess the default for $length is presumed to be positive? This should definitely be documented under the $start parameter, not $length. And so I think it's a stretch to say this has been documented.

If this was never *supposed* to work then I can see it's a documentation problem and will let it go.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue May 07 15:01:36 2024 UTC