summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2023-08-01 17:37:57 +0200
committerTakashi Kokubun <takashikkbn@gmail.com>2023-08-16 17:47:32 -0700
commitb6f26c2e4a95e71f67b84e36b4368d6d820ffb5b (patch)
tree8f68562f4f0970e8a30f23db478f7da0965e920c
parentab2f638a275ae8aaf55a4937dcb3f898cf7ddad0 (diff)
[ruby/yarp] Use common fields for yp_string_t
* Otherwise it is undefined behavior to access the field of another `.as`. * Accessing the right `.as` field according mode would be extra overhead. https://github.com/ruby/yarp/commit/7dc41ee803
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/8226
-rw-r--r--yarp/unescape.c6
-rw-r--r--yarp/util/yp_string.c49
-rw-r--r--yarp/util/yp_string.h27
-rw-r--r--yarp/yarp.c9
4 files changed, 28 insertions, 63 deletions
diff --git a/yarp/unescape.c b/yarp/unescape.c
index 3f6e70216c..32bfb6e53d 100644
--- a/yarp/unescape.c
+++ b/yarp/unescape.c
@@ -461,10 +461,8 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
return;
}
- yp_string_owned_init(string, allocated, length);
-
// This is the memory address where we're putting the unescaped string.
- char *dest = string->as.owned.source;
+ char *dest = allocated;
size_t dest_length = 0;
// This is the current position in the source string that we're looking at.
@@ -525,7 +523,7 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
// We also need to update the length at the end. This is because every escape
// reduces the length of the final string, and we don't want garbage at the
// end.
- string->as.owned.length = dest_length + ((size_t) (end - cursor));
+ yp_string_owned_init(string, allocated, dest_length + ((size_t) (end - cursor)));
}
YP_EXPORTED_FUNCTION bool
diff --git a/yarp/util/yp_string.c b/yarp/util/yp_string.c
index 12ae5537c0..4582263592 100644
--- a/yarp/util/yp_string.c
+++ b/yarp/util/yp_string.c
@@ -13,12 +13,11 @@
// Initialize a shared string that is based on initial input.
void
yp_string_shared_init(yp_string_t *string, const char *start, const char *end) {
+ assert(start <= end);
*string = (yp_string_t) {
.type = YP_STRING_SHARED,
- .as.shared = {
- .start = start,
- .end = end
- }
+ .source = (char*) start,
+ .length = (size_t) (end - start)
};
}
@@ -27,10 +26,8 @@ void
yp_string_owned_init(yp_string_t *string, char *source, size_t length) {
*string = (yp_string_t) {
.type = YP_STRING_OWNED,
- .as.owned = {
- .source = source,
- .length = length
- }
+ .source = source,
+ .length = length
};
}
@@ -39,10 +36,8 @@ void
yp_string_constant_init(yp_string_t *string, const char *source, size_t length) {
*string = (yp_string_t) {
.type = YP_STRING_CONSTANT,
- .as.constant = {
- .source = source,
- .length = length
- }
+ .source = (char*) source,
+ .length = length
};
}
@@ -50,10 +45,8 @@ static void
yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) {
*string = (yp_string_t) {
.type = YP_STRING_MAPPED,
- .as.mapped = {
- .source = source,
- .length = length
- }
+ .source = source,
+ .length = length
};
}
@@ -62,7 +55,7 @@ size_t
yp_string_memsize(const yp_string_t *string) {
size_t size = sizeof(yp_string_t);
if (string->type == YP_STRING_OWNED) {
- size += string->as.owned.length;
+ size += string->length;
}
return size;
}
@@ -77,40 +70,32 @@ yp_string_ensure_owned(yp_string_t *string) {
const char *source = yp_string_source(string);
yp_string_owned_init(string, malloc(length), length);
- memcpy(string->as.owned.source, source, length);
+ memcpy(string->source, source, length);
}
// Returns the length associated with the string.
YP_EXPORTED_FUNCTION size_t
yp_string_length(const yp_string_t *string) {
- if (string->type == YP_STRING_SHARED) {
- return (size_t) (string->as.shared.end - string->as.shared.start);
- } else {
- return string->as.owned.length;
- }
+ return string->length;
}
// Returns the start pointer associated with the string.
YP_EXPORTED_FUNCTION const char *
yp_string_source(const yp_string_t *string) {
- if (string->type == YP_STRING_SHARED) {
- return string->as.shared.start;
- } else {
- return string->as.owned.source;
- }
+ return string->source;
}
// Free the associated memory of the given string.
YP_EXPORTED_FUNCTION void
yp_string_free(yp_string_t *string) {
if (string->type == YP_STRING_OWNED) {
- free(string->as.owned.source);
- } else if (string->type == YP_STRING_MAPPED && string->as.mapped.length) {
- void *memory = (void *) string->as.mapped.source;
+ free(string->source);
+ } else if (string->type == YP_STRING_MAPPED && string->length) {
+ void *memory = (void *) string->source;
#if defined(_WIN32)
UnmapViewOfFile(memory);
#elif defined(HAVE_MMAP)
- munmap(memory, string->as.mapped.length);
+ munmap(memory, string->length);
#else
free(memory);
#endif
diff --git a/yarp/util/yp_string.h b/yarp/util/yp_string.h
index 4d9612674d..108915ce2d 100644
--- a/yarp/util/yp_string.h
+++ b/yarp/util/yp_string.h
@@ -3,6 +3,7 @@
#include "yarp/defines.h"
+#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
@@ -11,30 +12,12 @@
// This struct represents a string value.
typedef struct {
enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type;
-
- union {
- struct {
- const char *start;
- const char *end;
- } shared;
-
- struct {
- char *source;
- size_t length;
- } owned;
-
- struct {
- const char *source;
- size_t length;
- } constant;
-
- struct {
- char *source;
- size_t length;
- } mapped;
- } as;
+ char *source;
+ size_t length;
} yp_string_t;
+#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_CONSTANT, .source = NULL, .length = 0 })
+
// Initialize a shared string that is based on initial input.
void yp_string_shared_init(yp_string_t *string, const char *start, const char *end);
diff --git a/yarp/yarp.c b/yarp/yarp.c
index 83c4cc2ccf..61baae3a5f 100644
--- a/yarp/yarp.c
+++ b/yarp/yarp.c
@@ -445,7 +445,6 @@ not_provided(yp_parser_t *parser) {
return (yp_token_t) { .type = YP_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start };
}
-#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_SHARED, .as.shared.start = NULL, .as.shared.end = NULL })
#define YP_LOCATION_NULL_VALUE(parser) ((yp_location_t) { .start = parser->start, .end = parser->start })
#define YP_LOCATION_TOKEN_VALUE(token) ((yp_location_t) { .start = (token)->start, .end = (token)->end })
#define YP_LOCATION_NODE_VALUE(node) ((yp_location_t) { .start = (node)->location.start, .end = (node)->location.end })
@@ -9345,8 +9344,8 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
// Now get the bounds of the existing string. We'll use this as a
// destination to move bytes into. We'll also use it for bounds checking
// since we don't require that these strings be null terminated.
- size_t dest_length = string->as.owned.length;
- char *source_start = string->as.owned.source;
+ size_t dest_length = yp_string_length(string);
+ char *source_start = string->source;
const char *source_cursor = source_start;
const char *source_end = source_cursor + dest_length;
@@ -9400,7 +9399,7 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
dedent_next = true;
}
- string->as.owned.length = dest_length;
+ string->length = dest_length;
}
}
@@ -12450,7 +12449,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
yp_string_t *name = &named_captures.strings[index];
assert(name->type == YP_STRING_SHARED);
- yp_parser_local_add_location(parser, name->as.shared.start, name->as.shared.end);
+ yp_parser_local_add_location(parser, name->source, name->source + name->length);
}
}