aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/erlang.xml17
-rw-r--r--erts/emulator/beam/bif.c35
-rw-r--r--erts/emulator/beam/global.h2
-rw-r--r--erts/emulator/beam/utils.c60
-rw-r--r--erts/emulator/test/bif_SUITE.erl3
5 files changed, 65 insertions, 52 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 105734d5b2..11f2d36a01 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -1943,23 +1943,26 @@ os_prompt%</pre>
<item>The runtime system exits with integer value
<c><anno>Status</anno></c>
as status code to the calling environment (OS).
+ <note>
+ <p>On many platforms, the OS supports only status
+ codes 0-255. A too large status code is truncated by clearing
+ the high bits.</p>
+ </note>
</item>
<tag>string()</tag>
<item>An Erlang crash dump is produced with <c><anno>Status</anno></c>
as slogan. Then the runtime system exits with status code <c>1</c>.
- Note that only code points in the range 0-255 may be used
- and the string will be truncated if longer than 200 characters.
+ The string will be truncated if longer than 200 characters.
+ <note>
+ <p>Before ERTS 9.1 (OTP-20.1) only code points in the range 0-255
+ was accepted in the string. Now any unicode string is valid.</p>
+ </note>
</item>
<tag><c>abort</c></tag>
<item>The runtime system aborts producing a core dump, if that is
enabled in the OS.
</item>
</taglist>
- <note>
- <p>On many platforms, the OS supports only status
- codes 0-255. A too large status code is truncated by clearing
- the high bits.</p>
- </note>
<p>For integer <c><anno>Status</anno></c>, the Erlang runtime system
closes all ports and allows async threads to finish their
operations before exiting. To exit without such flushing, use
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 890277a3ba..52842a26eb 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -3018,17 +3018,17 @@ BIF_RETTYPE list_to_atom_1(BIF_ALIST_1)
{
Eterm res;
byte *buf = (byte *) erts_alloc(ERTS_ALC_T_TMP, MAX_ATOM_SZ_LIMIT);
- Sint i = erts_unicode_list_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS);
-
+ Sint written;
+ int i = erts_unicode_list_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS,
+ &written);
if (i < 0) {
erts_free(ERTS_ALC_T_TMP, (void *) buf);
- i = erts_list_length(BIF_ARG_1);
- if (i > MAX_ATOM_CHARACTERS) {
+ if (i == -2) {
BIF_ERROR(BIF_P, SYSTEM_LIMIT);
}
BIF_ERROR(BIF_P, BADARG);
}
- res = erts_atom_put(buf, i, ERTS_ATOM_ENC_UTF8, 1);
+ res = erts_atom_put(buf, written, ERTS_ATOM_ENC_UTF8, 1);
ASSERT(is_atom(res));
erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_RET(res);
@@ -3039,8 +3039,9 @@ BIF_RETTYPE list_to_atom_1(BIF_ALIST_1)
BIF_RETTYPE list_to_existing_atom_1(BIF_ALIST_1)
{
byte *buf = (byte *) erts_alloc(ERTS_ALC_T_TMP, MAX_ATOM_SZ_LIMIT);
- Sint i = erts_unicode_list_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS);
-
+ Sint written;
+ int i = erts_unicode_list_to_buf(BIF_ARG_1, buf, MAX_ATOM_CHARACTERS,
+ &written);
if (i < 0) {
error:
erts_free(ERTS_ALC_T_TMP, (void *) buf);
@@ -3048,7 +3049,7 @@ BIF_RETTYPE list_to_existing_atom_1(BIF_ALIST_1)
} else {
Eterm a;
- if (erts_atom_get((char *) buf, i, &a, ERTS_ATOM_ENC_UTF8)) {
+ if (erts_atom_get((char *) buf, written, &a, ERTS_ATOM_ENC_UTF8)) {
erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_RET(a);
} else {
@@ -3967,9 +3968,6 @@ BIF_RETTYPE display_nl_0(BIF_ALIST_0)
/**********************************************************************/
-#define HALT_MSG_SIZE 200
-static char halt_msg[HALT_MSG_SIZE+1];
-
/* stop the system with exit code and flags */
BIF_RETTYPE halt_2(BIF_ALIST_2)
{
@@ -4019,16 +4017,17 @@ BIF_RETTYPE halt_2(BIF_ALIST_2)
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_exit(ERTS_ABORT_EXIT, "");
}
- else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) {
- Sint i;
+ else if (is_list(BIF_ARG_1) || BIF_ARG_1 == NIL) {
+# define HALT_MSG_SIZE 200
+ static byte halt_msg[4*HALT_MSG_SIZE+1];
+ Sint written;
- if ((i = intlist_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE)) == -1) {
+ if (erts_unicode_list_to_buf(BIF_ARG_1, halt_msg, HALT_MSG_SIZE,
+ &written) == -1 ) {
goto error;
}
- if (i == -2) /* truncated string */
- i = HALT_MSG_SIZE;
- ASSERT(i >= 0 && i <= HALT_MSG_SIZE);
- halt_msg[i] = '\0';
+ ASSERT(written >= 0 && written < sizeof(halt_msg));
+ halt_msg[written] = '\0';
VERBOSE(DEBUG_SYSTEM,
("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2));
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 2105ee7a6c..717ecf5e6a 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1288,7 +1288,7 @@ int erts_utf8_to_latin1(byte* dest, const byte* source, int slen);
void bin_write(fmtfn_t, void*, byte*, size_t);
Sint intlist_to_buf(Eterm, char*, Sint); /* most callers pass plain char*'s */
-Sint erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len);
+int erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written);
struct Sint_buf {
#if defined(ARCH_64)
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 0fb25c2082..cb8d93549c 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -3635,30 +3635,40 @@ intlist_to_buf(Eterm list, char *buf, Sint len)
return -2; /* not enough space */
}
-/* Fill buf with the contents of the unicode list.
- * Return the number of bytes in the buffer,
- * or -1 for type error,
- * or -2 for not enough buffer space (buffer contains truncated result).
+/** @brief Fill buf with the UTF8 contents of the unicode list
+ * @param len Max number of characters to write.
+ * @param written NULL or bytes written.
+ * @return 0 ok,
+ * -1 type error,
+ * -2 list too long, only \c len characters written
*/
-Sint
-erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len)
+int
+erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written)
{
Eterm* listptr;
Sint sz = 0;
+ Sint val;
+ int res;
- if (is_nil(list)) {
- return 0;
- }
- if (is_not_list(list)) {
- return -1;
- }
- listptr = list_val(list);
+ while (1) {
+ if (is_nil(list)) {
+ res = 0;
+ break;
+ }
+ if (is_not_list(list)) {
+ res = -1;
+ break;
+ }
+ listptr = list_val(list);
- while (len-- > 0) {
- Sint val;
+ if (len-- <= 0) {
+ res = -2;
+ break;
+ }
if (is_not_small(CAR(listptr))) {
- return -1;
+ res = -1;
+ break;
}
val = signed_val(CAR(listptr));
if (0 <= val && val < 0x80) {
@@ -3670,7 +3680,8 @@ erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len)
sz += 2;
} else if (val < 0x10000UL) {
if (0xD800 <= val && val <= 0xDFFF) {
- return -1;
+ res = -1;
+ break;
}
buf[sz+0] = 0xE0 | (val >> 12);
buf[sz+1] = 0x80 | ((val >> 6) & 0x3F);
@@ -3683,18 +3694,15 @@ erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len)
buf[sz+3] = 0x80 | (val & 0x3F);
sz += 4;
} else {
- return -1;
+ res = -1;
+ break;
}
list = CDR(listptr);
- if (is_nil(list)) {
- return sz;
- }
- if (is_not_list(list)) {
- return -1;
- }
- listptr = list_val(list);
}
- return -2; /* not enough space */
+
+ if (written)
+ *written = sz;
+ return res;
}
/*
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index 339c827602..4908ac410c 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -691,6 +691,9 @@ erlang_halt(Config) when is_list(Config) ->
{badrpc,nodedown} = rpc:call(N3, erlang, halt, [0,[]]),
{ok,N4} = slave:start(H, halt_node4),
{badrpc,nodedown} = rpc:call(N4, erlang, halt, [lists:duplicate(300,$x)]),
+ %% Test unicode slogan
+ {ok,N4} = slave:start(H, halt_node4),
+ {badrpc,nodedown} = rpc:call(N4, erlang, halt, [[339,338,254,230,198,295,167,223,32,12507,12531,12480]]),
% This test triggers a segfault when dumping a crash dump
% to make sure that we can handle it properly.