Prohibit string changes by "s"/"z" specifier of `mrb_get_args()`
The `s` specifier is a string pointer obtained without performing `mrb_str_modify()`, so it cannot be changed.
The `z` specifier cannot be changed because it is a string pointer obtained by `RSTRING_CSTR()` which returns `const char *`.
MODIFY
include/mruby.h
include/mruby.h
@@ -876,8 +876,8 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
* | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` |
* | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` |
* | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` |
- * | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` |
- * | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` |
+ * | `s` | {String} | const char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` |
+ * | `z` | {String} | const char * | `NULL` terminated string; `z!` gives `NULL` for `nil` |
* | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` |
* | `f` | {Fixnum}/{Float} | {mrb_float} | |
* | `i` | {Fixnum}/{Float} | {mrb_int} | |

MODIFY
mrbgems/mruby-eval/src/eval.c
mrbgems/mruby-eval/src/eval.c
@@ -12,7 +12,7 @@ mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
void mrb_codedump_all(mrb_state*, struct RProc*);
static struct RProc*
-create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line)
+create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line)
{
mrbc_context *cxt;
struct mrb_parser_state *p;
@@ -131,10 +131,10 @@ exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
static mrb_value
f_eval(mrb_state *mrb, mrb_value self)
{
- char *s;
+ const char *s;
mrb_int len;
mrb_value binding = mrb_nil_value();
- char *file = NULL;
+ const char *file = NULL;
mrb_int line = 1;
struct RProc *proc;
@@ -154,9 +154,9 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "*!&", &argv, &argc, &b);
if (mrb_nil_p(b)) {
- char *s;
+ const char *s;
mrb_int len;
- char *file = NULL;
+ const char *file = NULL;
mrb_int line = 1;
mrb_value cv;
struct RProc *proc;

MODIFY
mrbgems/mruby-io/src/file.c
mrbgems/mruby-io/src/file.c
@@ -557,7 +557,8 @@ mrb_file_s_readlink(mrb_state *mrb, mrb_value klass) {
mrb_raise(mrb, E_NOTIMP_ERROR, "readlink is not supported on this platform");
return mrb_nil_value(); // unreachable
#else
- char *path, *buf, *tmp;
+ const char *path;
+ char *buf, *tmp;
size_t bufsize = 100;
ssize_t rc;
mrb_value ret;

MODIFY
mrbgems/mruby-socket/src/socket.c
mrbgems/mruby-socket/src/socket.c
@@ -515,7 +515,8 @@ static mrb_value
mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
{
mrb_int af, n;
- char *addr, buf[50];
+ const char *addr;
+ char buf[50];
mrb_get_args(mrb, "is", &af, &addr, &n);
if ((af == AF_INET && n != 4) || (af == AF_INET6 && n != 16))
@@ -529,7 +530,8 @@ static mrb_value
mrb_ipsocket_pton(mrb_state *mrb, mrb_value klass)
{
mrb_int af, n;
- char *bp, buf[50];
+ const char *bp;
+ char buf[50];
mrb_get_args(mrb, "is", &af, &bp, &n);
if ((size_t)n > sizeof(buf) - 1)

MODIFY
mrbgems/mruby-string-ext/src/string.c
mrbgems/mruby-string-ext/src/string.c
@@ -1072,7 +1072,8 @@ static mrb_value
mrb_str_del_prefix_bang(mrb_state *mrb, mrb_value self)
{
mrb_int plen, slen;
- char *ptr, *s;
+ const char *ptr;
+ char *s;
struct RString *str = RSTRING(self);
mrb_get_args(mrb, "s", &ptr, &plen);
@@ -1105,7 +1106,7 @@ static mrb_value
mrb_str_del_prefix(mrb_state *mrb, mrb_value self)
{
mrb_int plen, slen;
- char *ptr;
+ const char *ptr;
mrb_get_args(mrb, "s", &ptr, &plen);
slen = RSTRING_LEN(self);
@@ -1129,7 +1130,8 @@ static mrb_value
mrb_str_del_suffix_bang(mrb_state *mrb, mrb_value self)
{
mrb_int plen, slen;
- char *ptr, *s;
+ const char *ptr;
+ char *s;
struct RString *str = RSTRING(self);
mrb_get_args(mrb, "s", &ptr, &plen);
@@ -1160,7 +1162,7 @@ static mrb_value
mrb_str_del_suffix(mrb_state *mrb, mrb_value self)
{
mrb_int plen, slen;
- char *ptr;
+ const char *ptr;
mrb_get_args(mrb, "s", &ptr, &plen);
slen = RSTRING_LEN(self);

MODIFY
src/class.c
src/class.c
@@ -584,8 +584,8 @@ void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
S: String [mrb_value] when ! follows, the value may be nil
A: Array [mrb_value] when ! follows, the value may be nil
H: Hash [mrb_value] when ! follows, the value may be nil
- s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
- z: String [char*] NUL terminated string; z! gives NULL for nil
+ s: String [const char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
+ z: String [const char*] NUL terminated string; z! gives NULL for nil
a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil
c: Class/Module [strcut RClass*]
f: Fixnum/Float [mrb_float]
@@ -772,10 +772,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
case 's':
{
mrb_value ss;
- char **ps = 0;
+ const char **ps = 0;
mrb_int *pl = 0;
- ps = va_arg(ap, char**);
+ ps = va_arg(ap, const char**);
pl = va_arg(ap, mrb_int*);
if (i < argc) {
ss = argv[i++];

Prohibit string changes by "s"/"z" specifier of `mrb_get_args()`

- The `s` specifier is a string pointer obtained without performing `mrb_str_modify()`, so it cannot be changed.
- The `z` specifier cannot be changed because it is a string pointer obtained by `RSTRING_CSTR()` which returns `const char *`.