From 37379a2974190ab0fc97f840112d5a40c907368b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 29 Aug 2017 00:06:21 +0300 Subject: [PATCH] py/objstr: startswith, endswith: Check arg to be a string. Otherwise, it will silently get incorrect result on other values types, including CPython tuple form like "foo.png".endswith(("png", "jpg")) (which MicroPython doesn't support for unbloatedness). --- py/objstr.c | 6 ++++-- tests/basics/string_endswith.py | 5 +++++ tests/basics/string_endswith_upy.py | 6 ++++++ tests/basics/string_endswith_upy.py.exp | 1 + tests/basics/string_startswith.py | 5 +++++ tests/basics/string_startswith_upy.py | 6 ++++++ tests/basics/string_startswith_upy.py.exp | 1 + 7 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 tests/basics/string_endswith_upy.py create mode 100644 tests/basics/string_endswith_upy.py.exp create mode 100644 tests/basics/string_startswith_upy.py create mode 100644 tests/basics/string_startswith_upy.py.exp diff --git a/py/objstr.c b/py/objstr.c index d4c038a686..f04bd90be7 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -726,7 +726,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex); STATIC mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); GET_STR_DATA_LEN(args[0], str, str_len); - GET_STR_DATA_LEN(args[1], prefix, prefix_len); + size_t prefix_len; + const char *prefix = mp_obj_str_get_data(args[1], &prefix_len); const byte *start = str; if (n_args > 2) { start = str_index_to_ptr(self_type, str, str_len, args[2], true); @@ -740,7 +741,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith); STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { GET_STR_DATA_LEN(args[0], str, str_len); - GET_STR_DATA_LEN(args[1], suffix, suffix_len); + size_t suffix_len; + const char *suffix = mp_obj_str_get_data(args[1], &suffix_len); if (n_args > 2) { mp_raise_NotImplementedError("start/end indices"); } diff --git a/tests/basics/string_endswith.py b/tests/basics/string_endswith.py index 3e8fba925d..683562d10c 100644 --- a/tests/basics/string_endswith.py +++ b/tests/basics/string_endswith.py @@ -10,3 +10,8 @@ print("foobar".endswith("foobarbaz")) #print("1foo".startswith("1foo", 1)) #print("1fo".startswith("foo", 1)) #print("1fo".startswith("foo", 10)) + +try: + "foobar".endswith(1) +except TypeError: + print("TypeError") diff --git a/tests/basics/string_endswith_upy.py b/tests/basics/string_endswith_upy.py new file mode 100644 index 0000000000..06a4e71d2c --- /dev/null +++ b/tests/basics/string_endswith_upy.py @@ -0,0 +1,6 @@ +# MicroPython doesn't support tuple argument + +try: + "foobar".endswith(("bar", "sth")) +except TypeError: + print("TypeError") diff --git a/tests/basics/string_endswith_upy.py.exp b/tests/basics/string_endswith_upy.py.exp new file mode 100644 index 0000000000..6002b71c56 --- /dev/null +++ b/tests/basics/string_endswith_upy.py.exp @@ -0,0 +1 @@ +TypeError diff --git a/tests/basics/string_startswith.py b/tests/basics/string_startswith.py index 5cf730c03c..e63ae3c186 100644 --- a/tests/basics/string_startswith.py +++ b/tests/basics/string_startswith.py @@ -9,3 +9,8 @@ print("1foo".startswith("foo", 1)) print("1foo".startswith("1foo", 1)) print("1fo".startswith("foo", 1)) print("1fo".startswith("foo", 10)) + +try: + "foobar".startswith(1) +except TypeError: + print("TypeError") diff --git a/tests/basics/string_startswith_upy.py b/tests/basics/string_startswith_upy.py new file mode 100644 index 0000000000..9ea1796c21 --- /dev/null +++ b/tests/basics/string_startswith_upy.py @@ -0,0 +1,6 @@ +# MicroPython doesn't support tuple argument + +try: + "foobar".startswith(("foo", "sth")) +except TypeError: + print("TypeError") diff --git a/tests/basics/string_startswith_upy.py.exp b/tests/basics/string_startswith_upy.py.exp new file mode 100644 index 0000000000..6002b71c56 --- /dev/null +++ b/tests/basics/string_startswith_upy.py.exp @@ -0,0 +1 @@ +TypeError