Skip to content

String index fixes and cleanups #1937

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 12, 2014

Conversation

matthijskooijman
Copy link
Collaborator

This pullrequest adds support for using negative indices in Strings to index a String from the end instead of the start. This changes all methods that accept indices: operator[], charAt, setCharAt, indexOf, lastIndexOf, substring and remove.

I also added some fixes and simplifications I ran across while implementing the negative indices.

@matthijskooijman
Copy link
Collaborator Author

After some discussion on the developers list, I agreed that having a negative index feature is nice, but the extra overhead (54 bytes of program space even when not using it) is not worth it. I've removed the patch that added support for this, leaving just the related (but independently useful) bugfix and cleanup patches. I've added two more bugfixes related to invalid strings as well.

@matthijskooijman matthijskooijman changed the title String index fixes and allow negative indices String index fixes and cleanups Apr 24, 2014
@matthijskooijman matthijskooijman added Component: Core Related to the code for the standard Arduino API Version: 1.5.x feature request A request to make an enhancement (not a bug fix) labels Sep 10, 2014
@cmaglie cmaglie added this to the Release 1.5.8 milestone Sep 10, 2014
This check already happens in the remove(unsigned int, unsigned int)
method that is caled, so there is no need to also check this here.
Previously, if you passed in a very big index and/or count, the
`index + count` could overflow, making the count be used as-is instead
of being truncated (causing the string to be updated wrongly and
potentially writing to arbitrary memory locations).

We can rewrite the comparison to use `len - index` instead. Since we
know that index < len, we are sure this subtraction does not overflow,
regardless of what values of index and count we pass in.

As an added bonus, the `len - index` value already needed be calculated
inside the if, so this saves a few instructions in the generated code.

To illustrate this problem, consider this code:

String foo = "foo";
Serial.println(foo.length()); // Prints 3
foo.remove(1, 65535); // Should remove all but first character
Serial.println(foo.length()); // Prints 4 without this patch

Not shown in this is example is that some arbitrary memory is written
as well.
Previously, this method calculated the length of the string from the
given index onwards. However, the other remove() method called already
contains code for this calculation, which is used when the count passed
in is too big. This means we can just pass in a very big count that is
guaranteed to point past the end of the string, shrinking the remove
method by a few bytes.
When checking the `left` argument, it previously allowed having
left == len. However, this means the substring starts one past the last
character in the string and should return the empty string. In practice,
this already worked correctly, because buffer[len] contains the trailing
nul, so it would (re)assign the empty string to `out`.

However, fixing this check makes it a bit more logical, and prevents a
fairly unlikely out-of-buffer write (to address 0x0) when calling
substring on an invalidated String:

	String bar = (char*)NULL;
	bar.substring(0, 0);
@matthijskooijman
Copy link
Collaborator Author

I've rebased this commit, dropped two commits (of which the second reverted the first - apparently I removed a check in the first commit, thinking it wasn't needed and then re-added it later not realizing I removed it in an earlier commit) and slightly changed the last commit to fix the same (unlikely) problem in a different way. I also added some examples of code that would break in two of the commit messages.

@ffissore
Copy link
Contributor

@ArduinoBot build this please

@ArduinoBot
Copy link
Contributor

Merged build finished. Test PASSed.

cmaglie added a commit that referenced this pull request Sep 12, 2014
@cmaglie cmaglie merged commit 3d222cc into arduino:ide-1.5.x Sep 12, 2014
@cmaglie
Copy link
Member

cmaglie commented Sep 12, 2014

Thanks!

@matthijskooijman matthijskooijman deleted the stringindex branch June 12, 2015 15:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Core Related to the code for the standard Arduino API feature request A request to make an enhancement (not a bug fix)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants