Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
618224a
[Feature #20925] Support leading logical operators
nobu Dec 23, 2024
ff93185
Remove excludes
nobu Sep 13, 2025
91e5647
Get rid of `strcpy`
nobu Aug 19, 2025
9b40d2b
Stop at max dlext size
nobu Sep 12, 2025
bb5cd8e
Get rid of `strcpy` and magic numbers
nobu Sep 13, 2025
717ad9f
Remove an unused expression
nobu Sep 12, 2025
234f4c0
Fix dangling pointers
nobu Sep 12, 2025
9620964
Use API version for syntax version instead of program version
nobu Sep 13, 2025
caa5d8c
Exclude `JSON::GenericObject` test
nobu Sep 13, 2025
46095d2
auto-style.rb: Allow to adjust the given files
nobu Sep 13, 2025
ab3b582
auto-style.rb: Adjust .y file as same as .c
nobu Sep 13, 2025
d2cea4b
* adjust indents. [ci skip]
nobu Sep 13, 2025
ea8b346
Suppress warning from net/http.rb in ruby 3.1
nobu Aug 30, 2025
aaa9c19
[DOC] Markup the autolink excluded word library name `Set`
nobu Sep 13, 2025
c68a1c3
[DOC] [Feature #20925] Add leading logical to NEWS
nobu Sep 13, 2025
c5feae9
Remove stale line [ci skip]
nobu Sep 13, 2025
4f4b4e3
Fill in lead num for blocks with `it`
kddnewton Sep 13, 2025
d781d69
Fix prism error messages with multibyte truncation
kddnewton Sep 13, 2025
e745246
[ruby/prism] Revert "Merge pull request #3606 from tenderlove/clear-f…
k0kubun Sep 12, 2025
f4ce5e9
[ruby/prism] Bump to v1.5.1
kddnewton Sep 13, 2025
6c9408d
Update default gems list at f4ce5e90b2b9a4ccc7b4a0a25416c5 [ci skip]
matzbot Sep 13, 2025
b897a47
[ruby/prism] Documentation for Prism::Translation::Parser
kddnewton Sep 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ jobs:
- test_task: check
os: macos-15
extra_checks: [capi]
capi_check: capi
- test_task: check
os: macos-13
fail-fast: false
Expand Down
26 changes: 23 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ Note that each entry is kept to a minimum, see links for details.
* `*nil` no longer calls `nil.to_a`, similar to how `**nil` does
not call `nil.to_hash`. [[Feature #21047]]

* Logical binary operators (`||`, `&&`, `and` and `or`) at the
beginning of a line continue the previous line, like fluent dot.
The following two code are equal:

```ruby
if condition1
&& condition2
...
end
```

```ruby
if condition1 && condition2
...
end
```

[[Feature #20925]]

## Core classes updates

Note: We're only listing outstanding class updates.
Expand Down Expand Up @@ -98,9 +117,9 @@ Note: We're only listing outstanding class updates.

* `Ractor#close_incoming` and `Ractor#close_outgoing` were removed.

* Set
* `Set`

* Set is now a core class, instead of an autoloaded stdlib class.
* `Set` is now a core class, instead of an autoloaded stdlib class.
[[Feature #21216]]

* String
Expand Down Expand Up @@ -167,7 +186,7 @@ The following default gems are updated.
* io-wait 0.3.2
* json 2.13.2
* optparse 0.7.0.dev.2
* prism 1.5.0
* prism 1.5.1
* psych 5.2.6
* resolv 0.6.2
* stringio 3.1.8.dev
Expand Down Expand Up @@ -285,6 +304,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
[Feature #19908]: https://bugs.ruby-lang.org/issues/19908
[Feature #20610]: https://bugs.ruby-lang.org/issues/20610
[Feature #20724]: https://bugs.ruby-lang.org/issues/20724
[Feature #20925]: https://bugs.ruby-lang.org/issues/20925
[Feature #21047]: https://bugs.ruby-lang.org/issues/21047
[Bug #21049]: https://bugs.ruby-lang.org/issues/21049
[Feature #21166]: https://bugs.ruby-lang.org/issues/21166
Expand Down
5 changes: 3 additions & 2 deletions addr2line.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,12 +637,13 @@ follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_tr
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
{
static const char global_debug_dir[] = "/usr/lib/debug/.build-id/";
static const char debug_suffix[] = ".debug";
const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
char *p;
obj_info_t *o1 = *objp, *o2;
size_t i;

if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6) return;
if (PATH_MAX < global_debug_dir_len + build_id_size * 2 + sizeof(debug_suffix)) return;

memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
p = binary_filename + global_debug_dir_len;
Expand All @@ -653,7 +654,7 @@ follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_tr
*p++ = tbl[n % 16];
if (i == 0) *p++ = '/';
}
strcpy(p, ".debug");
memcpy(p, debug_suffix, sizeof(debug_suffix));

append_obj(objp);
o2 = *objp;
Expand Down
2 changes: 0 additions & 2 deletions depend
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,6 @@ compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
compile.$(OBJEXT): $(top_srcdir)/prism/version.h
compile.$(OBJEXT): $(top_srcdir)/prism_compile.c
compile.$(OBJEXT): $(top_srcdir)/version.h
compile.$(OBJEXT): {$(VPATH)}assert.h
compile.$(OBJEXT): {$(VPATH)}atomic.h
compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h
Expand Down Expand Up @@ -1606,7 +1605,6 @@ compile.$(OBJEXT): {$(VPATH)}prism_compile.h
compile.$(OBJEXT): {$(VPATH)}ractor.h
compile.$(OBJEXT): {$(VPATH)}re.h
compile.$(OBJEXT): {$(VPATH)}regex.h
compile.$(OBJEXT): {$(VPATH)}revision.h
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
compile.$(OBJEXT): {$(VPATH)}rubyparser.h
Expand Down
4 changes: 1 addition & 3 deletions ext/socket/getaddrinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,7 @@ static const char *const ai_errlist[] = {

#define GET_CANONNAME(ai, str) \
if (pai->ai_flags & AI_CANONNAME) {\
if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
strcpy((ai)->ai_canonname, (str));\
} else {\
if (((ai)->ai_canonname = strdup(str)) == NULL) {\
error = EAI_MEMORY;\
goto free;\
}\
Expand Down
15 changes: 5 additions & 10 deletions ext/socket/getnameinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,14 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
/* what we should do? */
} else if (flags & NI_NUMERICSERV) {
snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
if (strlen(numserv) + 1 > servlen)
if (strlcpy(serv, numserv, servlen) >= servlen)
return ENI_MEMORY;
strcpy(serv, numserv);
} else {
#if defined(HAVE_GETSERVBYPORT)
struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
if (sp) {
if (strlen(sp->s_name) + 1 > servlen)
if (strlcpy(serv, sp->s_name, servlen) >= servlen)
return ENI_MEMORY;
strcpy(serv, sp->s_name);
} else
return ENI_NOSERVNAME;
#else
Expand Down Expand Up @@ -202,9 +200,8 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_SYSTEM;
if (strlen(numaddr) > hostlen)
if (strlcpy(host, numaddr, hostlen) >= hostlen)
return ENI_MEMORY;
strcpy(host, numaddr);
} else {
#ifdef INET6
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
Expand All @@ -218,13 +215,12 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
p = strchr(hp->h_name, '.');
if (p) *p = '\0';
}
if (strlen(hp->h_name) + 1 > hostlen) {
if (strlcpy(host, hp->h_name, hostlen) >= hostlen) {
#ifdef INET6
freehostent(hp);
#endif
return ENI_MEMORY;
}
strcpy(host, hp->h_name);
#ifdef INET6
freehostent(hp);
#endif
Expand All @@ -234,9 +230,8 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_NOHOSTNAME;
if (strlen(numaddr) > hostlen)
if (strlcpy(host, numaddr, hostlen) >= hostlen)
return ENI_MEMORY;
strcpy(host, numaddr);
}
}
return SUCCESS;
Expand Down
17 changes: 9 additions & 8 deletions ext/socket/ipsocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ rsock_init_inetsock(
VALUE self, VALUE remote_host, VALUE remote_serv,
VALUE local_host, VALUE local_serv, int type,
VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout,
VALUE _fast_fallback, VALUE _test_mode_settings
) {
VALUE _fast_fallback, VALUE _test_mode_settings)
{
if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) {
rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout");
}
Expand Down Expand Up @@ -423,8 +423,8 @@ select_expires_at(
struct timeval *connection_attempt_delay,
struct timeval *user_specified_resolv_timeout_at,
struct timeval *user_specified_connect_timeout_at,
struct timeval *user_specified_open_timeout_at
) {
struct timeval *user_specified_open_timeout_at)
{
if (any_addrinfos(resolution_store)) {
struct timeval *delay;
delay = resolution_delay ? resolution_delay : connection_attempt_delay;
Expand Down Expand Up @@ -526,7 +526,8 @@ in_progress_fds(int fds_size)
}

static void
remove_connection_attempt_fd(int *fds, int *fds_size, int removing_fd) {
remove_connection_attempt_fd(int *fds, int *fds_size, int removing_fd)
{
int i, j;

for (i = 0; i < *fds_size; i++) {
Expand Down Expand Up @@ -1283,8 +1284,8 @@ rsock_init_inetsock(
VALUE self, VALUE remote_host, VALUE remote_serv,
VALUE local_host, VALUE local_serv, int type,
VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout,
VALUE fast_fallback, VALUE test_mode_settings
) {
VALUE fast_fallback, VALUE test_mode_settings)
{
if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) {
rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout");
}
Expand Down Expand Up @@ -1315,7 +1316,7 @@ rsock_init_inetsock(
);

struct addrinfo *tmp_p = local_res->ai;
for (tmp_p; tmp_p != NULL; tmp_p = tmp_p->ai_next) {
for (; tmp_p != NULL; tmp_p = tmp_p->ai_next) {
if (target_families[0] == 0 && tmp_p->ai_family == AF_INET6) {
target_families[0] = AF_INET6;
resolving_family_size++;
Expand Down
4 changes: 2 additions & 2 deletions ext/socket/raddrinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,15 @@ allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addr

if (hostp) {
arg->node = buf + hostp_offset;
strcpy(arg->node, hostp);
memcpy(arg->node, hostp, portp_offset - hostp_offset);
}
else {
arg->node = NULL;
}

if (portp) {
arg->service = buf + portp_offset;
strcpy(arg->service, portp);
memcpy(arg->service, portp, bufsize - portp_offset);
}
else {
arg->service = NULL;
Expand Down
11 changes: 6 additions & 5 deletions gc/default/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -4392,15 +4392,16 @@ static inline void
gc_mark_check_t_none(rb_objspace_t *objspace, VALUE obj)
{
if (RB_UNLIKELY(RB_TYPE_P(obj, T_NONE))) {
char obj_info_buf[256];
rb_raw_obj_info(obj_info_buf, 256, obj);
enum {info_size = 256};
char obj_info_buf[info_size];
rb_raw_obj_info(obj_info_buf, info_size, obj);

char parent_obj_info_buf[256];
char parent_obj_info_buf[info_size];
if (objspace->rgengc.parent_object == Qfalse) {
strcpy(parent_obj_info_buf, "(none)");
strlcpy(parent_obj_info_buf, "(none)", info_size);
}
else {
rb_raw_obj_info(parent_obj_info_buf, 256, objspace->rgengc.parent_object);
rb_raw_obj_info(parent_obj_info_buf, info_size, objspace->rgengc.parent_object);
}

rb_bug("try to mark T_NONE object (obj: %s, parent: %s)", obj_info_buf, parent_obj_info_buf);
Expand Down
2 changes: 1 addition & 1 deletion lib/prism/prism.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Gem::Specification.new do |spec|
spec.name = "prism"
spec.version = "1.5.0"
spec.version = "1.5.1"
spec.authors = ["Shopify"]
spec.email = ["ruby@shopify.com"]

Expand Down
9 changes: 8 additions & 1 deletion lib/prism/translation/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ module Translation
# whitequark/parser gem's syntax tree. It inherits from the base parser for
# the parser gem, and overrides the parse* methods to parse with prism and
# then translate.
#
# Note that this version of the parser always parses using the latest
# version of Ruby syntax supported by Prism. If you want specific version
# support, use one of the version-specific subclasses, such as
# `Prism::Translation::Parser34`. If you want to parse using the same
# version of Ruby syntax as the currently running version of Ruby, use
# `Prism::Translation::ParserCurrent`.
class Parser < ::Parser::Base
Diagnostic = ::Parser::Diagnostic # :nodoc:
private_constant :Diagnostic
Expand Down Expand Up @@ -77,7 +84,7 @@ def initialize(builder = Prism::Translation::Parser::Builder.new, parser: Prism)
end

def version # :nodoc:
34
35
end

# The default encoding for Ruby files is UTF-8.
Expand Down
28 changes: 16 additions & 12 deletions namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -725,28 +725,32 @@ copy_ext_file(char *src_path, char *dst_path)
#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)

static void
fname_without_suffix(char *fname, char *rvalue)
fname_without_suffix(const char *fname, char *rvalue, size_t rsize)
{
char *pos;
strcpy(rvalue, fname);
for (pos = rvalue + strlen(fname); pos > rvalue; pos--) {
size_t len = strlen(fname);
const char *pos;
for (pos = fname + len; pos > fname; pos--) {
if (IS_SOEXT(pos) || IS_DLEXT(pos)) {
*pos = '\0';
return;
len = pos - fname;
break;
}
if (fname + len - pos > DLEXT_MAXLEN) break;
}
if (len > rsize - 1) len = rsize - 1;
memcpy(rvalue, fname, len);
rvalue[len] = '\0';
}

static void
escaped_basename(char *path, char *fname, char *rvalue)
escaped_basename(const char *path, const char *fname, char *rvalue, size_t rsize)
{
char *pos, *leaf, *found;
leaf = path;
char *pos;
const char *leaf = path, *found;
// `leaf + 1` looks uncomfortable (when leaf == path), but fname must not be the top-dir itself
while ((found = strstr(leaf + 1, fname)) != NULL) {
leaf = found; // find the last occurrence for the path like /etc/my-crazy-lib-dir/etc.so
}
strcpy(rvalue, leaf);
strlcpy(rvalue, leaf, rsize);
for (pos = rvalue; *pos; pos++) {
if (isdirsep(*pos)) {
*pos = '+';
Expand All @@ -762,8 +766,8 @@ rb_namespace_local_extension(VALUE namespace, VALUE fname, VALUE path)
char *src_path = RSTRING_PTR(path), *fname_ptr = RSTRING_PTR(fname);
rb_namespace_t *ns = rb_get_namespace_t(namespace);

fname_without_suffix(fname_ptr, fname2);
escaped_basename(src_path, fname2, basename);
fname_without_suffix(fname_ptr, fname2, sizeof(fname2));
escaped_basename(src_path, fname2, basename, sizeof(basename));

wrote = sprint_ext_filename(ext_path, sizeof(ext_path), ns->ns_id, NAMESPACE_TMP_PREFIX, basename);
if (wrote >= (int)sizeof(ext_path)) {
Expand Down
Loading