diff options
49 files changed, 852 insertions, 230 deletions
diff --git a/HOWTO/INSTALL.md b/HOWTO/INSTALL.md index c53cfdc6ec..51e8648a4a 100644 --- a/HOWTO/INSTALL.md +++ b/HOWTO/INSTALL.md @@ -210,6 +210,14 @@ the `$PATH`. $ export PATH=$ERL_TOP/bin:$PATH # Assuming bash/sh +For the FOP print formatter, two steps must be taken: + +* Adding the location of your installation of `fop` in `$FOP_HOME`. + + $ export FOP_HOME=/path/to/fop/dir # Assuming bash/sh + +* Adding the `fop` script (in `$FOP_HOME`) to your `$PATH`, either by adding `$FOP_HOME` to `$PATH`, or by copying the `fop` script to a directory already in your `$PATH`. + Build the documentation. $ make docs diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 0492924164..70d000f763 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -874,10 +874,10 @@ </item> <tag><c>line</c></tag> <item> - <p>A packet is a line terminated with newline. The - newline character is included in the returned packet - unless the line was truncated according to option - <c>line_length</c>.</p> + <p>A packet is a line terminated by a delimiter byte, + default is the latin1 newline character. The delimiter + byte is included in the returned packet unless the line + was truncated according to option <c>line_length</c>.</p> </item> <tag><c>asn1 | cdr | sunrm | fcgi | tpkt</c></tag> <item> @@ -933,6 +933,10 @@ if <c>packet_size</c> itself is not set. This use is only intended for backward compatibility.</p> </item> + <tag><c>{line_delimiter, 0 =< byte() =< 255}</c></tag> + <item><p>For packet type <c>line</c>, sets the delimiting byte. + Default is the latin1 character <c>$\n</c>.</p> + </item> </taglist> <p>Examples:</p> <pre> diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index f9a2f3e33e..190e7817dc 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -321,6 +321,7 @@ atom ldflags atom Le='=<' atom lf atom line +atom line_delimiter atom line_length atom linked_in_driver atom links diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index c774a70d4c..90985e4f53 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -79,7 +79,7 @@ erts_debug_breakpoint_2(BIF_ALIST_2) { Process* p = BIF_P; Eterm MFA = BIF_ARG_1; - Eterm bool = BIF_ARG_2; + Eterm boolean = BIF_ARG_2; Eterm* tp; Eterm mfa[3]; int i; @@ -87,7 +87,7 @@ erts_debug_breakpoint_2(BIF_ALIST_2) Eterm res; BpFunctions f; - if (bool != am_true && bool != am_false) + if (boolean != am_true && boolean != am_false) goto error; if (is_not_tuple(MFA)) { @@ -124,7 +124,7 @@ erts_debug_breakpoint_2(BIF_ALIST_2) erts_smp_thr_progress_block(); erts_bp_match_functions(&f, mfa, specified); - if (bool == am_true) { + if (boolean == am_true) { erts_set_debug_break(&f); erts_install_breakpoints(&f); erts_commit_staged_bp(); diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 4e3a1cef69..0bd46a2dae 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -616,7 +616,7 @@ erts_queue_monitor_message(Process *p, } static BIF_RETTYPE -local_pid_monitor(Process *p, Eterm target, Eterm mon_ref, int bool) +local_pid_monitor(Process *p, Eterm target, Eterm mon_ref, int boolean) { BIF_RETTYPE ret; Process *rp; @@ -634,7 +634,7 @@ local_pid_monitor(Process *p, Eterm target, Eterm mon_ref, int bool) if (!rp) { erts_smp_proc_unlock(p, ERTS_PROC_LOCK_LINK); p_locks &= ~ERTS_PROC_LOCK_LINK; - if (bool) + if (boolean) ret = am_false; else erts_queue_monitor_message(p, &p_locks, @@ -643,7 +643,7 @@ local_pid_monitor(Process *p, Eterm target, Eterm mon_ref, int bool) else { ASSERT(rp != p); - if (bool) + if (boolean) ret = am_true; erts_add_monitor(&ERTS_P_MONITORS(p), MON_ORIGIN, mon_ref, target, NIL); diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 23897a49ae..0bbcc5f966 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -45,6 +45,8 @@ #include "erl_thr_progress.h" #include "dtrace-wrapper.h" +#define DIST_CTL_DEFAULT_SIZE 64 + /* Turn this on to get printouts of all distribution messages * which go on the line */ @@ -66,9 +68,13 @@ static void bw(byte *buf, ErlDrvSizeT sz) static void dist_msg_dbg(ErtsDistExternal *edep, char *what, byte *buf, int sz) { + ErtsHeapFactory factory; + DeclareTmpHeapNoproc(ctl_default,DIST_CTL_DEFAULT_SIZE); + Eterm* ctl = ctl_default; byte *extp = edep->extp; Eterm msg; - Sint size = erts_decode_dist_ext_size(edep); + Sint ctl_len; + Sint size = ctl_len = erts_decode_dist_ext_size(edep); if (size < 0) { erts_fprintf(stderr, "DIST MSG DEBUG: erts_decode_dist_ext_size(%s) failed:\n", @@ -76,10 +82,9 @@ dist_msg_dbg(ErtsDistExternal *edep, char *what, byte *buf, int sz) bw(buf, sz); } else { - Eterm *hp; ErlHeapFragment *mbuf = new_message_buffer(size); - hp = mbuf->mem; - msg = erts_decode_dist_ext(&hp, &mbuf->off_heap, edep); + erts_factory_static_init(&factory, ctl, ctl_len, &mbuf->off_heap); + msg = erts_decode_dist_ext(&factory, edep); if (is_value(msg)) erts_fprintf(stderr, " %s: %T\n", what, msg); else { @@ -1136,7 +1141,6 @@ int erts_net_message(Port *prt, byte *buf, ErlDrvSizeT len) { -#define DIST_CTL_DEFAULT_SIZE 64 ErtsDistExternal ede; byte *t; Sint ctl_len; @@ -1790,8 +1794,8 @@ erts_dsig_send(ErtsDSigData *dsdp, struct erts_dsig_send_context* ctx) #ifdef ERTS_DIST_MSG_DBG erts_fprintf(stderr, ">>%s CTL: %T\n", ctx->pass_through_size ? "P" : " ", ctx->ctl); - if (is_value(msg)) - erts_fprintf(stderr, " MSG: %T\n", msg); + if (is_value(ctx->msg)) + erts_fprintf(stderr, " MSG: %T\n", ctx->msg); #endif ctx->data_size = ctx->pass_through_size; diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 3ff54c7a60..e47d7bcbbb 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -1329,7 +1329,8 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3) ErlSubBin* rest; Eterm res; Eterm options; - int code; + int code; + char delimiter = '\n'; if (!is_binary(BIF_ARG_2) || (!is_list(BIF_ARG_3) && !is_nil(BIF_ARG_3))) { @@ -1370,6 +1371,11 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3) case am_line_length: trunc_len = val; goto next_option; + case am_line_delimiter: + if (type == TCP_PB_LINE_LF && val >= 0 && val <= 255) { + delimiter = (char)val; + goto next_option; + } } } } @@ -1390,7 +1396,7 @@ BIF_RETTYPE decode_packet_3(BIF_ALIST_3) pca.aligned_ptr = bin_ptr; } packet_sz = packet_get_length(type, (char*)pca.aligned_ptr, pca.bin_sz, - max_plen, trunc_len, &http_state); + max_plen, trunc_len, delimiter, &http_state); if (!(packet_sz > 0 && packet_sz <= pca.bin_sz)) { if (packet_sz < 0) { goto error; diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c index 2dd421a9e9..a737a86f14 100644 --- a/erts/emulator/beam/packet_parser.c +++ b/erts/emulator/beam/packet_parser.c @@ -256,6 +256,7 @@ int packet_get_length(enum PacketParseType htype, const char* ptr, unsigned n, /* Bytes read so far */ unsigned max_plen, /* Max packet length, 0=no limit */ unsigned trunc_len, /* Truncate (lines) if longer, 0=no limit */ + char delimiter, /* Line delimiting character */ int* statep) /* Protocol specific state */ { unsigned hlen, plen; @@ -299,9 +300,9 @@ int packet_get_length(enum PacketParseType htype, goto remain; case TCP_PB_LINE_LF: { - /* TCP_PB_LINE_LF: [Data ... \n] */ + /* TCP_PB_LINE_LF: [Data ... Delimiter] */ const char* ptr2; - if ((ptr2 = memchr(ptr, '\n', n)) == NULL) { + if ((ptr2 = memchr(ptr, delimiter, n)) == NULL) { if (n > max_plen && max_plen != 0) { /* packet full */ DEBUGF((" => packet full (no NL)=%d\r\n", n)); goto error; diff --git a/erts/emulator/beam/packet_parser.h b/erts/emulator/beam/packet_parser.h index ff158ff8b8..717d905fad 100644 --- a/erts/emulator/beam/packet_parser.h +++ b/erts/emulator/beam/packet_parser.h @@ -105,7 +105,8 @@ int packet_get_length(enum PacketParseType htype, const char* ptr, unsigned n, /* Bytes read so far */ unsigned max_plen, /* Packet max length, 0=no limit */ unsigned trunc_len, /* Truncate (lines) if longer, 0=no limit */ - int* statep); /* Internal protocol state */ + char delimiter, /* Line delimiting character */ + int* statep); /* Internal protocol state */ ERTS_GLB_INLINE void packet_get_body(enum PacketParseType htype, diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 89b71aa66a..a829599fe5 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -885,6 +885,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) #define INET_LOPT_MSGQ_LOWTRMRK 37 /* set local msgq low watermark */ #define INET_LOPT_NETNS 38 /* Network namespace pathname */ #define INET_LOPT_TCP_SHOW_ECONNRESET 39 /* tell user about incoming RST */ +#define INET_LOPT_LINE_DELIM 40 /* Line delimiting char */ /* SCTP options: a separate range, from 100: */ #define SCTP_OPT_RTOINFO 100 #define SCTP_OPT_ASSOCINFO 101 @@ -1154,6 +1155,7 @@ typedef struct { #else Uint32 send_oct[2]; /* number of octets sent, 64 bits */ #endif + char delimiter; /* Line delimiting character (def: '\n') */ unsigned long send_cnt; /* number of packets sent */ unsigned long send_max; /* maximum packet send */ double send_avg; /* average packet size sent */ @@ -6276,6 +6278,12 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len) } continue; + case INET_LOPT_LINE_DELIM: + DEBUGF(("inet_set_opts(%ld): s=%d, LINE_DELIM=%d\r\n", + (long)desc->port, desc->s, ival)); + desc->delimiter = (char)ival; + continue; + case INET_OPT_REUSEADDR: #ifdef __WIN32__ continue; /* Bjorn says */ @@ -8371,6 +8379,7 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol) desc->deliver = INET_DELIVER_TERM; /* standard term format */ desc->active = INET_PASSIVE; /* start passive */ desc->active_count = 0; + desc->delimiter = '\n'; /* line delimiting char */ desc->oph = NULL; desc->opt = NULL; @@ -9882,7 +9891,7 @@ static int tcp_remain(tcp_descriptor* desc, int* len) tlen = packet_get_length(desc->inet.htype, ptr, n, desc->inet.psize, desc->i_bufsz, - &desc->http_state); + desc->inet.delimiter, &desc->http_state); DEBUGF(("tcp_remain(%ld): s=%d, n=%d, nfill=%d nsz=%d, tlen %d\r\n", (long)desc->inet.port, desc->inet.s, n, nfill, nsz, tlen)); diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 4c311e1f06..97aa5e573e 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1478,7 +1478,15 @@ processes_this_tab(doc) -> processes_this_tab(suite) -> []; processes_this_tab(Config) when is_list(Config) -> - sys_mem_cond_run(1024, fun () -> chk_processes_bif_test_res(processes_bif_test()) end). + Mem = case {erlang:system_info(build_type), + erlang:system_info(allocator)} of + {lcnt, {_, _Vsn, [sys_alloc], _Opts}} -> + %% When running +Mea min + lcnt we may need more memory + 1024 * 4; + _ -> + 1024 + end, + sys_mem_cond_run(Mem, fun () -> chk_processes_bif_test_res(processes_bif_test()) end). chk_processes_bif_test_res(ok) -> ok; chk_processes_bif_test_res({comment, _} = Comment) -> Comment; diff --git a/erts/etc/win32/msys_tools/vc/cc.sh b/erts/etc/win32/msys_tools/vc/cc.sh index ad05e5375b..ac89aac34e 100644 --- a/erts/etc/win32/msys_tools/vc/cc.sh +++ b/erts/etc/win32/msys_tools/vc/cc.sh @@ -242,7 +242,7 @@ for x in $SOURCES; do if [ $PREPROCESSING = true ]; then output_flag="-E" else - output_flag="-c -Fo`cmd //C echo ${output_filename}`" + output_flag="-FS -c -Fo`cmd //C echo ${output_filename}`" fi params="$COMMON_CFLAGS $MD $DEBUG_FLAGS $OPTIMIZE_FLAGS \ $CMD ${output_flag} $MPATH" @@ -250,6 +250,8 @@ for x in $SOURCES; do echo cc.sh "$SAVE" >>$CC_SH_DEBUG_LOG echo cl.exe $params >>$CC_SH_DEBUG_LOG fi + # MSYS2 (currently) converts the paths wrong, avoid it + export MSYS2_ARG_CONV_EXCL=-FoC eval cl.exe $params >$MSG_FILE 2>$ERR_FILE RES=$? if test $PREPROCESSING = false; then @@ -274,6 +276,7 @@ for x in $SOURCES; do fi rm -f $ERR_FILE $MSG_FILE if [ $RES != 0 ]; then + echo Failed: cl.exe $params rm -rf $TMPOBJDIR exit $RES fi @@ -312,7 +315,10 @@ if [ $LINKING = true ]; then stdlib="-lLIBMTD";; esac # And finally call the next script to do the linking... - params="$out_spec $LINKCMD $stdlib" + params="$out_spec $LINKCMD $stdlib" + if [ "X$CC_SH_DEBUG_LOG" != "X" ]; then + echo ld.sh $ACCUM_OBJECTS $params + fi eval ld.sh $ACCUM_OBJECTS $params RES=$? fi diff --git a/erts/etc/win32/msys_tools/vc/emu_cc.sh b/erts/etc/win32/msys_tools/vc/emu_cc.sh index 01f75b2468..10d59214ea 100644 --- a/erts/etc/win32/msys_tools/vc/emu_cc.sh +++ b/erts/etc/win32/msys_tools/vc/emu_cc.sh @@ -29,6 +29,7 @@ WTOOLDIR0=`win2msys_path.sh "$TOOLDIR"` WTOOLDIR=`cmd //C echo $WTOOLDIR0` # Do primitive 'make' newer_exe=`find $TOOLDIR -newer $COFFIX.c -name coffix.exe -print` +export MSYS2_ARG_CONV_EXCL="-FeC" if [ -z $newer_exe ]; then echo recompiling $COFFIX.exe cl.exe -Fe${WTOOLDIR}/coffix.exe ${WTOOLDIR}/coffix.c diff --git a/erts/etc/win32/msys_tools/vc/mc.sh b/erts/etc/win32/msys_tools/vc/mc.sh index e9ea9ff9a9..14b5ebaa8f 100644 --- a/erts/etc/win32/msys_tools/vc/mc.sh +++ b/erts/etc/win32/msys_tools/vc/mc.sh @@ -80,9 +80,14 @@ if [ -n "$OUTPUT_DIRNAME" ]; then exit $RES fi fi +# MSYS2 (currently) converts the paths wrong, avoid it +export MSYS2_ARG_CONV_EXCL= eval $MCC "$CMD" >/tmp/mc.exe.${p}.1 2>/tmp/mc.exe.${p}.2 RES=$? -tail +2 /tmp/mc.exe.${p}.2 >&2 +if [ $RES != 0 ]; then + echo Failed: $MCC "$CMD" +fi +tail -n +2 /tmp/mc.exe.${p}.2 >&2 cat /tmp/mc.exe.${p}.1 rm -f /tmp/mc.exe.${p}.2 /tmp/mc.exe.${p}.1 exit $RES diff --git a/erts/etc/win32/msys_tools/vc/rc.sh b/erts/etc/win32/msys_tools/vc/rc.sh index 1b3b1c85bd..1f8ade17cb 100644 --- a/erts/etc/win32/msys_tools/vc/rc.sh +++ b/erts/etc/win32/msys_tools/vc/rc.sh @@ -79,9 +79,14 @@ if [ "X$RC_SH_DEBUG_LOG" != "X" ]; then echo rc.sh "$SAVE" >>$RC_SH_DEBUG_LOG echo rc.exe $CMD >>$RC_SH_DEBUG_LOG fi +# MSYS2 (currently) converts the paths wrong, avoid it +export MSYS2_ARG_CONV_EXCL=-Fo eval $RCC "$CMD" >/tmp/rc.exe.${p}.1 2>/tmp/rc.exe.${p}.2 RES=$? -tail +2 /tmp/rc.exe.${p}.2 >&2 +if [ $RES != 0 ]; then + echo Failed: $RCC "$CMD" +fi +tail -n +2 /tmp/rc.exe.${p}.2 >&2 cat /tmp/rc.exe.${p}.1 rm -f /tmp/rc.exe.${p}.2 /tmp/rc.exe.${p}.1 exit $RES diff --git a/erts/etc/win32/nsis/Makefile b/erts/etc/win32/nsis/Makefile index 49d835170a..64f44ff86d 100644 --- a/erts/etc/win32/nsis/Makefile +++ b/erts/etc/win32/nsis/Makefile @@ -42,7 +42,13 @@ include $(ERL_TOP)/make/otp_release_targets.mk TARGET_DIR = $(RELEASE_PATH) -ifeq ($(MSYSTEM),MINGW32) +ifdef MSYSTEM + ifeq ($(MSYSTEM),$(filter $(MSYSTEM),MSYS MINGW32 MINGW64)) + USEMSYS := true + endif +endif + +ifeq ($(USEMSYS),true) MAKENSISFLAGS = //V2 WTESTROOT=$(shell (msys2win_path.sh "$(RELEASE_PATH)")) @@ -63,7 +69,7 @@ else endif REDIST_FILE=$(shell (sh ./find_redist.sh || echo "")) -ifeq ($(MSYSTEM),MINGW32) +ifeq ($(USEMSYS),true) NICEREDISTFILE=$(shell (msys2win_path.sh -m "$(REDIST_FILE)" 2>/dev/null || echo "")) else NICEREDISTFILE=$(shell (cygpath -d -m "$(REDIST_FILE)" 2>/dev/null || echo "")) diff --git a/erts/etc/win32/nsis/find_redist.sh b/erts/etc/win32/nsis/find_redist.sh index c0895c9dd5..03e92b21c7 100755 --- a/erts/etc/win32/nsis/find_redist.sh +++ b/erts/etc/win32/nsis/find_redist.sh @@ -164,7 +164,7 @@ fi #echo $BPATH_LIST for BP in $BPATH_LIST; do - for verdir in "sdk v2.0" "sdk v3.5" "v6.0A" "v7.0" "v7.0A" "v7.1"; do + for verdir in "sdk v2.0" "sdk v3.5" "v6.0A" "v7.0" "v7.0A" "v7.1" "VC redist 1033"; do BPATH=$BP fail=false allow_fail=false diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex 5a188be3ba..8b87d1ae26 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 4e55f711b2..7280b43502 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1974,6 +1974,7 @@ localtime_to_universaltime(_Localtime, _IsDst) -> %% CHECK! Why the strange very thorough specification of the error %% condition with disallowed arity in erl_bif_types? %% Not documented +%% Shadowed by erl_bif_types: erlang:make_fun/3 -spec erlang:make_fun(Module, Function, Arity) -> function() when Module :: atom(), Function :: atom(), diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl index 4d04e1dacb..d5c8fd4268 100644 --- a/erts/preloaded/src/prim_inet.erl +++ b/erts/preloaded/src/prim_inet.erl @@ -1147,6 +1147,7 @@ enc_opt(packet_size) -> ?INET_LOPT_PACKET_SIZE; enc_opt(read_packets) -> ?INET_LOPT_READ_PACKETS; enc_opt(netns) -> ?INET_LOPT_NETNS; enc_opt(show_econnreset) -> ?INET_LOPT_TCP_SHOW_ECONNRESET; +enc_opt(line_delimiter) -> ?INET_LOPT_LINE_DELIM; enc_opt(raw) -> ?INET_OPT_RAW; % Names of SCTP opts: enc_opt(sctp_rtoinfo) -> ?SCTP_OPT_RTOINFO; @@ -1205,6 +1206,7 @@ dec_opt(?INET_LOPT_PACKET_SIZE) -> packet_size; dec_opt(?INET_LOPT_READ_PACKETS) -> read_packets; dec_opt(?INET_LOPT_NETNS) -> netns; dec_opt(?INET_LOPT_TCP_SHOW_ECONNRESET) -> show_econnreset; +dec_opt(?INET_LOPT_LINE_DELIM) -> line_delimiter; dec_opt(?INET_OPT_RAW) -> raw; dec_opt(I) when is_integer(I) -> undefined. @@ -1287,6 +1289,7 @@ type_opt_1(packet) -> {httph_bin,?TCP_PB_HTTPH_BIN}, {ssl, ?TCP_PB_SSL_TLS}, % obsolete {ssl_tls, ?TCP_PB_SSL_TLS}]}; +type_opt_1(line_delimiter) -> int; type_opt_1(mode) -> {enum,[{list, ?INET_MODE_LIST}, {binary, ?INET_MODE_BINARY}]}; diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_arity b/lib/dialyzer/test/small_SUITE_data/results/fun_arity new file mode 100644 index 0000000000..280f5490d0 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/fun_arity @@ -0,0 +1,35 @@ + +fun_arity.erl:100: Fun application will fail since _cor1 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:100: Function 'Mfa_0_ko'/1 has no local return +fun_arity.erl:104: Fun application will fail since _cor1 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:104: Function 'Mfa_1_ko'/1 has no local return +fun_arity.erl:111: Fun application will fail since _cor1 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:111: Function mFa_0_ko/1 has no local return +fun_arity.erl:115: Fun application will fail since _cor1 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:115: Function mFa_1_ko/1 has no local return +fun_arity.erl:122: Fun application will fail since _cor2 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:122: Function 'MFa_0_ko'/2 has no local return +fun_arity.erl:126: Fun application will fail since _cor2 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:126: Function 'MFa_1_ko'/2 has no local return +fun_arity.erl:35: Fun application will fail since _cor0 :: fun(() -> 'ok') is not a function of arity 1 +fun_arity.erl:35: Function f_0_ko/0 has no local return +fun_arity.erl:39: Fun application will fail since _cor0 :: fun((_) -> 'ok') is not a function of arity 0 +fun_arity.erl:39: Function f_1_ko/0 has no local return +fun_arity.erl:48: Fun application will fail since _cor0 :: fun(() -> 'ok') is not a function of arity 1 +fun_arity.erl:48: Function fa_0_ko/0 has no local return +fun_arity.erl:53: Fun application will fail since _cor0 :: fun((_) -> 'ok') is not a function of arity 0 +fun_arity.erl:53: Function fa_1_ko/0 has no local return +fun_arity.erl:63: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:63: Function mfa_0_ko/0 has no local return +fun_arity.erl:68: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:68: Function mfa_1_ko/0 has no local return +fun_arity.erl:76: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:76: Function mfa_ne_0_ko/0 has no local return +fun_arity.erl:78: Function mf_ne/0 will never be called +fun_arity.erl:81: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:81: Function mfa_ne_1_ko/0 has no local return +fun_arity.erl:83: Function mf_ne/1 will never be called +fun_arity.erl:89: Fun application will fail since _cor0 :: fun(() -> any()) is not a function of arity 1 +fun_arity.erl:89: Function mfa_nd_0_ko/0 has no local return +fun_arity.erl:93: Fun application will fail since _cor0 :: fun((_) -> any()) is not a function of arity 0 +fun_arity.erl:93: Function mfa_nd_1_ko/0 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl new file mode 100644 index 0000000000..850d2fd331 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/fun_arity.erl @@ -0,0 +1,127 @@ +%%-------------------------------------------------------------------------- +%% Module which contains calls to funs of different arity. +%%-------------------------------------------------------------------------- +-module(fun_arity). + +-export([f_0_ok/0, f_0_ko/0]). +-export([f_1_ok/0, f_1_ko/0]). + +-export([fa_0_ok/0, fa_0_ko/0]). +-export([fa_1_ok/0, fa_1_ko/0]). + +-export([mfa_0_ok/0, mfa_0_ko/0, mf/0]). +-export([mfa_1_ok/0, mfa_1_ko/0, mf/1]). + +-export([mfa_ne_0_ok/0, mfa_ne_0_ko/0]). +-export([mfa_ne_1_ok/0, mfa_ne_1_ko/0]). + +-export([mfa_nd_0_ok/0, mfa_nd_0_ko/0]). +-export([mfa_nd_1_ok/0, mfa_nd_1_ko/0]). + +-export(['Mfa_0_ok'/1, 'Mfa_0_ko'/1]). +-export(['Mfa_1_ok'/1, 'Mfa_1_ko'/1]). + +-export(['mFa_0_ok'/1, 'mFa_0_ko'/1]). +-export(['mFa_1_ok'/1, 'mFa_1_ko'/1]). + +-export(['MFa_0_ok'/2, 'MFa_0_ko'/2]). +-export(['MFa_1_ok'/2, 'MFa_1_ko'/2]). + +%%-------------------------------------------------------------------------- + +%% Funs like "fun(...) -> ... end". + +f_0_ok() -> (fun_f_0())(). +f_0_ko() -> (fun_f_0())(1). +fun_f_0() -> fun() -> ok end. + +f_1_ok() -> (fun_f_1())(1). +f_1_ko() -> (fun_f_1())(). +fun_f_1() -> fun(_) -> ok end . + +%%-------------------------------------------------------------------------- + +%% Funs like "fun F/A" when F is literal atom and A is literal +%% non-negative integer. + +fa_0_ok() -> (fun_fa_0())(). +fa_0_ko() -> (fun_fa_0())(1). +fun_fa_0() -> fun f/0. +f() -> ok. + +fa_1_ok() -> (fun_fa_1())(1). +fa_1_ko() -> (fun_fa_1())(). +fun_fa_1() -> fun f/1. +f(_) -> ok. + +%%-------------------------------------------------------------------------- + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is (defined and) exported. + +mfa_0_ok() -> (fun_mfa_0())(). +mfa_0_ko() -> (fun_mfa_0())(1). +fun_mfa_0() -> fun ?MODULE:mf/0. +mf() -> ok. + +mfa_1_ok() -> (fun_mfa_1())(1). +mfa_1_ko() -> (fun_mfa_1())(). +fun_mfa_1() -> fun ?MODULE:mf/1. +mf(_) -> ok. + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is defined but not exported. + +mfa_ne_0_ok() -> (fun_mfa_ne_0())(). +mfa_ne_0_ko() -> (fun_mfa_ne_0())(1). +fun_mfa_ne_0() -> fun ?MODULE:mf_ne/0. +mf_ne() -> ok. + +mfa_ne_1_ok() -> (fun_mfa_ne_1())(1). +mfa_ne_1_ko() -> (fun_mfa_ne_1())(). +fun_mfa_ne_1() -> fun ?MODULE:mf_ne/1. +mf_ne(_) -> ok. + +%% Funs like "fun M:F/A" when M and F are literal atoms, A is literal +%% non-negative integer and function is not defined. + +mfa_nd_0_ok() -> (fun_mfa_nd_0())(). +mfa_nd_0_ko() -> (fun_mfa_nd_0())(1). +fun_mfa_nd_0() -> fun ?MODULE:mf_nd/0. + +mfa_nd_1_ok() -> (fun_mfa_nd_1())(1). +mfa_nd_1_ko() -> (fun_mfa_nd_1())(). +fun_mfa_nd_1() -> fun ?MODULE:mf_nd/1. + +%% Funs like "fun M:F/A" when M is variable, F is literal atoms and A +%% is literal non-negative integer. + +'Mfa_0_ok'(M) -> ('fun_Mfa_0'(M))(). +'Mfa_0_ko'(M) -> ('fun_Mfa_0'(M))(1). +'fun_Mfa_0'(M) -> fun M:f/0. + +'Mfa_1_ok'(M) -> ('fun_Mfa_1'(M))(1). +'Mfa_1_ko'(M) -> ('fun_Mfa_1'(M))(). +'fun_Mfa_1'(M) -> fun M:f/1. + +%% Funs like "fun M:F/A" when M is literal atom, F is variable and A +%% is literal non-negative integer. + +'mFa_0_ok'(F) -> ('fun_mFa_0'(F))(). +'mFa_0_ko'(F) -> ('fun_mFa_0'(F))(1). +'fun_mFa_0'(F) -> fun ?MODULE:F/0. + +'mFa_1_ok'(F) -> ('fun_mFa_1'(F))(1). +'mFa_1_ko'(F) -> ('fun_mFa_1'(F))(). +'fun_mFa_1'(F) -> fun ?MODULE:F/1. + +%% Funs like "fun M:F/A" when M and F are variables and A is literal +%% non-negative integer. + +'MFa_0_ok'(M, F) -> ('fun_MFa_0'(M, F))(). +'MFa_0_ko'(M, F) -> ('fun_MFa_0'(M, F))(1). +'fun_MFa_0'(M, F) -> fun M:F/0. + +'MFa_1_ok'(M, F) -> ('fun_MFa_1'(M, F))(1). +'MFa_1_ko'(M, F) -> ('fun_MFa_1'(M, F))(). +'fun_MFa_1'(M, F) -> fun M:F/1. diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 5387edfb47..c2fb79c089 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -768,6 +768,18 @@ type(erlang, length, 1, Xs, Opaques) -> %% Guard bif, needs to be here. type(erlang, map_size, 1, Xs, Opaques) -> strict(erlang, map_size, 1, Xs, fun (_) -> t_non_neg_integer() end, Opaques); +type(erlang, make_fun, 3, Xs, Opaques) -> + strict(erlang, make_fun, 3, Xs, + fun ([_, _, Arity]) -> + case t_number_vals(Arity, Opaques) of + [N] -> + case is_integer(N) andalso 0 =< N andalso N =< 255 of + true -> t_fun(N, t_any()); + false -> t_none() + end; + _Other -> t_fun() + end + end, Opaques); type(erlang, make_tuple, 2, Xs, Opaques) -> strict(erlang, make_tuple, 2, Xs, fun ([Int, _]) -> @@ -2361,6 +2373,8 @@ arg_types(erlang, length, 1) -> %% Guard bif, needs to be here. arg_types(erlang, map_size, 1) -> [t_map()]; +arg_types(erlang, make_fun, 3) -> + [t_atom(), t_atom(), t_arity()]; arg_types(erlang, make_tuple, 2) -> [t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument arg_types(erlang, make_tuple, 3) -> diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml index 47c40da96a..64e6c7a6cc 100644 --- a/lib/inets/doc/src/http_uri.xml +++ b/lib/inets/doc/src/http_uri.xml @@ -117,7 +117,8 @@ <v>Options = [Option]</v> <v>Option = {ipv6_host_with_brackets, boolean()} | {scheme_defaults, scheme_defaults()} | - {fragment, boolean()}]</v> + {fragment, boolean()} | + {schema_validation_fun, fun()}]</v> <v>Result = {Scheme, UserInfo, Host, Port, Path, Query} | {Scheme, UserInfo, Host, Port, Path, Query, Fragment}</v> <v>UserInfo = user_info()</v> @@ -141,6 +142,16 @@ <p>If the fragment option is <c>true</c>, the URI fragment is returned as part of the parsing result, otherwise it is ignored.</p> + <p>Scheme validation fun is to be defined as follows: + + <code> +fun(SchemeStr :: string()) -> + valid | {error, Reason :: term()}. + </code> + + It is called before scheme string gets converted into scheme atom and + thus possible atom leak could be prevented</p> + <marker id="encode"></marker> </desc> </func> diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl index 58b30c4e9e..d13670700c 100644 --- a/lib/inets/src/http_lib/http_response.erl +++ b/lib/inets/src/http_lib/http_response.erl @@ -31,16 +31,11 @@ %% Value - string() %% %% Description: Creates a http_response_h-record used internally to -%% handle http-headers. +%% handle http-headers, assumes reversed list of headers +%% to unfold multiline headers with obs-folds %%------------------------------------------------------------------------- -headers([], Headers) -> - Headers; - -headers([Header | Tail], Headers) -> - {Key, [$: | Value]} = - lists:splitwith(fun($:) -> false; (_) -> true end, Header), - headers(Tail, headers(http_util:to_lower(string:strip(Key)), - string:strip(Value), Headers)). +headers(RevLines, Headers) -> + fill_headers(RevLines, [], Headers). %%------------------------------------------------------------------------- %% headers(#http_response_h{}) -> HeaderList @@ -68,6 +63,23 @@ header_list(Headers) -> %%%======================================================================== %%% Internal functions %%%======================================================================== +fill_headers([], _, Headers) -> + Headers; +fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers) + when Ch == $\t; Ch == $\s -> + fill_headers(Tail, [HeaderFold|Folded], Headers); +fill_headers([Header | Tail], Folded, Headers) -> + Unfolded = unfold([Header|Folded]), + {Key, [$: | Value]} = + lists:splitwith(fun($:) -> false; (_) -> true end, Unfolded), + fill_headers(Tail, [], headers(http_util:to_lower(string:strip(Key)), + string:strip(Value), Headers)). + +unfold([L]) -> + L; +unfold(Folded) -> + string:join(Folded, " "). + headers("cache-control", Value, Headers) -> Headers#http_response_h{'cache-control'= Value}; headers("connection", Value, Headers) -> diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl index 79591eec29..6fe8c1776d 100644 --- a/lib/inets/src/http_lib/http_uri.erl +++ b/lib/inets/src/http_lib/http_uri.erl @@ -138,16 +138,33 @@ parse_scheme(AbsURI, Opts) -> {error, no_scheme} -> {error, no_scheme}; {SchemeStr, Rest} -> - Scheme = list_to_atom(http_util:to_lower(SchemeStr)), - SchemeDefaults = which_scheme_defaults(Opts), - case lists:keysearch(Scheme, 1, SchemeDefaults) of - {value, {Scheme, DefaultPort}} -> - {Scheme, DefaultPort, Rest}; - false -> - {Scheme, no_default_port, Rest} + case extract_scheme(SchemeStr, Opts) of + {error, Error} -> + {error, Error}; + {ok, Scheme} -> + SchemeDefaults = which_scheme_defaults(Opts), + case lists:keysearch(Scheme, 1, SchemeDefaults) of + {value, {Scheme, DefaultPort}} -> + {Scheme, DefaultPort, Rest}; + false -> + {Scheme, no_default_port, Rest} + end end end. +extract_scheme(Str, Opts) -> + case lists:keysearch(scheme_validation_fun, 1, Opts) of + {value, {scheme_validation_fun, Fun}} when is_function(Fun) -> + case Fun(Str) of + valid -> + {ok, list_to_atom(http_util:to_lower(Str))}; + {error, Error} -> + {error, Error} + end; + _ -> + {ok, list_to_atom(http_util:to_lower(Str))} + end. + parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) -> {Authority, PathQueryFragment} = split_uri(URIPart, "[/?#]", {URIPart, ""}, 1, 0), diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 5b40d08859..2ad00bdf76 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -105,6 +105,7 @@ only_simulated() -> internal_server_error, invalid_http, headers_dummy, + headers_with_obs_fold, empty_response_header, remote_socket_close, remote_socket_close_async, @@ -893,6 +894,13 @@ headers_dummy(Config) when is_list(Config) -> %%------------------------------------------------------------------------- +headers_with_obs_fold(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/obs_folded_headers.html", Config), []}, + {ok, {{_,200,_}, Headers, [_|_]}} = httpc:request(get, Request, [], []), + "a b" = proplists:get_value("folded", Headers). + +%%------------------------------------------------------------------------- + invalid_headers(Config) -> Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]}, {error, _} = httpc:request(get, Request, [], []). @@ -1713,6 +1721,13 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) -> send(Socket, http_chunk:encode("obar</BODY></HTML>")), http_chunk:encode_last(); +handle_uri(_,"/obs_folded_headers.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" + "Content-Length:5\r\n" + "Folded: a\r\n" + " b\r\n\r\n" + "Hello"; + handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Transfer-Encoding:Chunked\r\n\r\n", diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl index bfcd7bd339..2642b8fd4e 100644 --- a/lib/inets/test/uri_SUITE.erl +++ b/lib/inets/test/uri_SUITE.erl @@ -49,7 +49,8 @@ all() -> queries, fragments, escaped, - hexed_query + hexed_query, + scheme_validation ]. %%-------------------------------------------------------------------- @@ -175,6 +176,26 @@ hexed_query(Config) when is_list(Config) -> verify_uri(URI2, Verify2), verify_uri(URI3, Verify3). +scheme_validation(Config) when is_list(Config) -> + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment"), + + ValidationFun = + fun("http") -> valid; + (_) -> {error, bad_scheme} + end, + + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + {error, bad_scheme} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + %% non-fun scheme_validation_fun works as no option passed + {ok, {https,[],"localhost",443,"/",""}} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, none}]). + %%-------------------------------------------------------------------- %% Internal Functions ------------------------------------------------ diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index e5d7ce048a..e6d418dc58 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -981,6 +981,11 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp indicated length are accepted and not considered invalid due to internal buffer limitations.</p> </item> + <tag><c>{line_delimiter, Char}</c>(TCP/IP sockets)</tag> + <item> + <p>Sets the line delimiting character for line oriented protocols + (<c>line</c>). Default value is <c>$\n</c>.</p> + </item> <tag><c>{priority, Priority}</c></tag> <item> <p>Set the protocol-defined priority for all packets to be sent diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index da7f04089d..855c6377a3 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -671,7 +671,7 @@ stats() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% connect_options() -> [tos, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay, - header, active, packet, packet_size, buffer, mode, deliver, + header, active, packet, packet_size, buffer, mode, deliver, line_delimiter, exit_on_close, high_watermark, low_watermark, high_msgq_watermark, low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw, show_econnreset]. @@ -721,6 +721,8 @@ con_opt([Opt | Opts], #connect_opts{} = R, As) -> {active,N} when is_integer(N), N < 32768, N >= -32768 -> NOpts = lists:keydelete(active, 1, R#connect_opts.opts), con_opt(Opts, R#connect_opts { opts = [{active,N}|NOpts] }, As); + {line_delimiter,C} when is_integer(C), C >= 0, C =< 255 -> + con_add(line_delimiter, C, R, Opts, As); {Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As); _ -> {error, badarg} end; diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl index bfe4c9ec8c..e7c6cf8ae2 100644 --- a/lib/kernel/src/inet_int.hrl +++ b/lib/kernel/src/inet_int.hrl @@ -149,6 +149,7 @@ -define(INET_LOPT_MSGQ_LOWTRMRK, 37). -define(INET_LOPT_NETNS, 38). -define(INET_LOPT_TCP_SHOW_ECONNRESET, 39). +-define(INET_LOPT_LINE_DELIM, 40). % Specific SCTP options: separate range: -define(SCTP_OPT_RTOINFO, 100). -define(SCTP_OPT_ASSOCINFO, 101). diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl index c3840f3d16..dd3010567a 100644 --- a/lib/kernel/test/bif_SUITE.erl +++ b/lib/kernel/test/bif_SUITE.erl @@ -33,6 +33,7 @@ spawn_failures/1, run_fun/1, + decode_packet_delim/1, wilderness/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -516,6 +517,15 @@ fetch_proc_vals(Pid) -> {value,{heap_size,HS}} = lists:keysearch(heap_size, 1, PI), ?line {Ls, P, FA, HS}. +decode_packet_delim(doc) -> + ["Test erlang:packet_delim/3 with {line_delimiter,0} option"]; +decode_packet_delim(suite) -> + []; +decode_packet_delim(Config) when is_list(Config) -> + {ok,<<"abc",0>>,<<"efg",0>>} = + erlang:decode_packet(line, <<"abc",0,"efg",0>>, [{line_delimiter, 0}]), + {more, undefined} = erlang:decode_packet(line, <<"abc",0,"efg",0>>, []). + % This testcase should probably be moved somewhere else wilderness(doc) -> ["Test that memory allocation command line options affecting the" diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index a051d504b2..962471c20c 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -31,7 +31,7 @@ init_per_testcase/2, end_per_testcase/2, t_connect_timeout/1, t_accept_timeout/1, t_connect_bad/1, - t_recv_timeout/1, t_recv_eof/1, + t_recv_timeout/1, t_recv_eof/1, t_recv_delim/1, t_shutdown_write/1, t_shutdown_both/1, t_shutdown_error/1, t_shutdown_async/1, t_fdopen/1, t_fdconnect/1, t_implicit_inet6/1]). @@ -48,7 +48,7 @@ all() -> groups() -> [{t_accept, [], [t_accept_timeout]}, {t_connect, [], [t_connect_timeout, t_connect_bad]}, - {t_recv, [], [t_recv_timeout, t_recv_eof]}]. + {t_recv, [], [t_recv_timeout, t_recv_eof, t_recv_delim]}]. @@ -131,6 +131,21 @@ t_recv_eof(Config) when is_list(Config) -> ?line {error, closed} = gen_tcp:recv(Client, 0), ok. +t_recv_delim(doc) -> "Test using message delimiter $X"; +t_recv_delim(suite) -> []; +t_recv_delim(Config) when is_list(Config) -> + {ok, L} = gen_tcp:listen(0, []), + {ok, Port} = inet:port(L), + Opts = [{active,false},{packet,line},{line_delimiter,$X}], + {ok, Client} = gen_tcp:connect(localhost, Port, Opts), + {ok, A} = gen_tcp:accept(L), + ok = gen_tcp:send(A, "abcXefgX"), + {ok, "abcX"} = gen_tcp:recv(Client, 0, 0), + {ok, "efgX"} = gen_tcp:recv(Client, 0, 0), + ok = gen_tcp:close(Client), + ok = gen_tcp:close(A), + ok. + %%% gen_tcp:shutdown/2 t_shutdown_write(Config) when is_list(Config) -> diff --git a/lib/observer/src/cdv_ets_cb.erl b/lib/observer/src/cdv_ets_cb.erl index 9e6e72e08d..bac8b56fc3 100644 --- a/lib/observer/src/cdv_ets_cb.erl +++ b/lib/observer/src/cdv_ets_cb.erl @@ -97,7 +97,7 @@ info_fields() -> [{"Id", id}, {"Name", name}, {"Slot", slot}, - {"Owner", owner}, + {"Owner", pid}, {"Data Structure", data_type} ]}, {"Settings", diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index f2ce51b2af..b66b4d59c9 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -1572,7 +1572,7 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{fixed=>Val}},WS); "Type" -> Val = val(Fd), - get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{data_type=>Val}},WS); + get_etsinfo(Fd,EtsTable#ets_table{data_type=Val},WS); "Protection" -> Val = val(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{protection=>Val}},WS); diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml index 1a11806211..2065627026 100644 --- a/lib/runtime_tools/doc/src/dbg.xml +++ b/lib/runtime_tools/doc/src/dbg.xml @@ -1030,9 +1030,9 @@ hello</pre> <fsummary>Stop the <c>dbg</c>server and the tracing of all processes.</fsummary> <desc> <p>Stops the <c>dbg</c> server and clears all trace flags for - all processes and all trace patterns for all functions. Also + all processes and all local trace patterns for all functions. Also shuts down all trace clients and closes all trace ports.</p> - <p>Note that no trace patterns are affected by this + <p>Note that no global trace patterns are affected by this function.</p> </desc> </func> @@ -1040,8 +1040,7 @@ hello</pre> <name>stop_clear() -> ok</name> <fsummary>Stop the <c>dbg</c>server and the tracing of all processes, and clears trace patterns.</fsummary> <desc> - <p>Same as stop/0, but also clears all trace patterns on local - and global functions calls.</p> + <p>Same as stop/0, but also clears all trace patterns on global functions calls.</p> </desc> </func> </funcs> diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index 743282ce9c..03c2ce53cb 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -46,7 +46,8 @@ suite() -> all() -> [{group,tool_tests}, - {group,kex} + {group,kex}, + {group,service_requests} ]. groups() -> @@ -61,7 +62,13 @@ groups() -> gex_client_init_default_exact, gex_client_init_option_groups, gex_client_init_option_groups_file - ]} + ]}, + {service_requests, [], [bad_service_name, + bad_long_service_name, + bad_very_long_service_name, + empty_service_name, + bad_service_name_then_correct + ]} ]. @@ -114,25 +121,10 @@ end_per_testcase(_TestCase, Config) -> %%% Connect to an erlang server and check that the testlib acts as a client. lib_works_as_client(Config) -> %% Connect and negotiate keys - {ok,InitialState} = - ssh_trpt_test_lib:exec( - [{set_options, [print_ops, print_seqnums, print_messages]}, - {connect, - server_host(Config),server_port(Config), - [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, - {silently_accept_hosts, true}, - {user_dir, user_dir(Config)}, - {user_interaction, false}]}, - receive_hello, - {send, hello}, - {send, ssh_msg_kexinit}, - {match, #ssh_msg_kexinit{_='_'}, receive_msg}, - {send, ssh_msg_kexdh_init}, - {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, - {send, #ssh_msg_newkeys{}}, - {match, #ssh_msg_newkeys{_='_'}, receive_msg} - ] - ), + {ok,InitialState} = ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}] + ), + {ok,AfterKexState} = connect_and_kex(Config, InitialState), %% Do the authentcation {User,Pwd} = server_user_password(Config), @@ -147,7 +139,7 @@ lib_works_as_client(Config) -> ?STRING(unicode:characters_to_binary(Pwd))>> }}, {match, #ssh_msg_userauth_success{_='_'}, receive_msg} - ], InitialState), + ], AfterKexState), %% Disconnect {ok,_} = @@ -375,6 +367,48 @@ do_gex_client_init(Config, {Min,N,Max}, {_,{G,P}}) -> ] ). + +%%%-------------------------------------------------------------------- +bad_service_name(Config) -> + bad_service_name(Config, "kfglkjf"). + +bad_long_service_name(Config) -> + bad_service_name(Config, + lists:duplicate(?SSH_MAX_PACKET_SIZE div 2, $a)). + +bad_very_long_service_name(Config) -> + bad_service_name(Config, + lists:duplicate(4*?SSH_MAX_PACKET_SIZE, $a)). + +empty_service_name(Config) -> + bad_service_name(Config, ""). + +bad_service_name_then_correct(Config) -> + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, #ssh_msg_service_request{name = "kdjglkfdjgkldfjglkdfjglkfdjglkj"}}, + {send, #ssh_msg_service_request{name = "ssh-connection"}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + + +bad_service_name(Config, Name) -> + {ok,InitialState} = connect_and_kex(Config), + {ok,_} = + ssh_trpt_test_lib:exec( + [{set_options, [print_ops, print_seqnums, print_messages]}, + {send, #ssh_msg_service_request{name = Name}}, + {match, {'or',[#ssh_msg_disconnect{_='_'}, + tcp_closed + ]}, + receive_msg} + ], InitialState). + %%%================================================================ %%%==== Internal functions ======================================== %%%================================================================ @@ -482,3 +516,24 @@ std_connect(Host, Port, Config, Opts) -> 30000). %%%---------------------------------------------------------------- +connect_and_kex(Config) -> + connect_and_kex(Config, ssh_trpt_test_lib:exec([]) ). + +connect_and_kex(Config, InitialState) -> + ssh_trpt_test_lib:exec( + [{connect, + server_host(Config),server_port(Config), + [{preferred_algorithms,[{kex,['diffie-hellman-group1-sha1']}]}, + {silently_accept_hosts, true}, + {user_dir, user_dir(Config)}, + {user_interaction, false}]}, + receive_hello, + {send, hello}, + {send, ssh_msg_kexinit}, + {match, #ssh_msg_kexinit{_='_'}, receive_msg}, + {send, ssh_msg_kexdh_init}, + {match,# ssh_msg_kexdh_reply{_='_'}, receive_msg}, + {send, #ssh_msg_newkeys{}}, + {match, #ssh_msg_newkeys{_='_'}, receive_msg} + ], + InitialState). diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl index 9daa6efc02..ef631d54bd 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -89,9 +89,10 @@ rekey_limit(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "rekey.data"), - {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 4500}]), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000}, + {max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), @@ -132,13 +133,13 @@ renegotiate1(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate1.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), @@ -170,12 +171,12 @@ renegotiate2(Config) -> UserDir = ?config(priv_dir, Config), DataFile = filename:join(UserDir, "renegotiate2.data"), - {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[]), + {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0}]), RPort = ssh_test_lib:inet_port(), {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort), - ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, []), + ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]), {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef), Kex1 = get_kex_init(ConnectionRef), diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 168b8a695a..d1dfa2efdf 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -53,7 +53,7 @@ groups() -> erlang_client_openssh_server_kexs, erlang_client_openssh_server_nonexistent_subsystem ]}, - {erlang_server, [], [erlang_server_openssh_client_pulic_key_dsa]} + {erlang_server, [], [erlang_server_openssh_client_public_key_dsa]} ]. init_per_suite(Config) -> @@ -95,7 +95,7 @@ end_per_group(_, Config) -> Config. -init_per_testcase(erlang_server_openssh_client_pulic_key_dsa, Config) -> +init_per_testcase(erlang_server_openssh_client_public_key_dsa, Config) -> case ssh_test_lib:openssh_supports(sshc, public_key, 'ssh-dss') of true -> init_per_testcase('__default__',Config); @@ -350,9 +350,9 @@ erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> {skip, "no ~/.ssh/id_dsa"} end. %%-------------------------------------------------------------------- -erlang_server_openssh_client_pulic_key_dsa() -> +erlang_server_openssh_client_public_key_dsa() -> [{doc, "Validate using dsa publickey."}]. -erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) -> +erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) -> SystemDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), KnownHosts = filename:join(PrivDir, "known_hosts"), diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml index c556180b8b..faf668735e 100644 --- a/lib/stdlib/doc/src/beam_lib.xml +++ b/lib/stdlib/doc/src/beam_lib.xml @@ -224,6 +224,13 @@ <funcs> <func> + <name name="all_chunks" arity="1"/> + <fsummary>Read all chunks from a BEAM file or binary</fsummary> + <desc> + <p>Reads chunk data for all chunks.</p> + </desc> + </func> + <func> <name name="chunks" arity="2"/> <fsummary>Read selected chunks from a BEAM file or binary</fsummary> <desc> @@ -251,6 +258,13 @@ </desc> </func> <func> + <name name="build_module" arity="1"/> + <fsummary>Creates a BEAM module from a list of chunks</fsummary> + <desc> + <p>Builds a BEAM module (as a binary) from a list of chunks.</p> + </desc> + </func> + <func> <name name="version" arity="1"/> <fsummary>Read the BEAM file's module version</fsummary> <desc> diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml index 19ddf1cbd6..966eec49f5 100644 --- a/lib/stdlib/doc/src/unicode.xml +++ b/lib/stdlib/doc/src/unicode.xml @@ -133,7 +133,7 @@ <c>latin1</c>, or have characters encoded as one of the UTF-encodings, which is given as the <c><anno>InEncoding</anno></c> parameter. Only when the <c><anno>InEncoding</anno></c> is one of the UTF - encodings, integers in the list are allowed to be grater than + encodings, integers in the list are allowed to be greater than 255.</p> <p>If <c><anno>InEncoding</anno></c> is <c>latin1</c>, the <c><anno>Data</anno></c> parameter diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl index b93ce97cd3..cbbab088f4 100644 --- a/lib/stdlib/src/beam_lib.erl +++ b/lib/stdlib/src/beam_lib.erl @@ -308,6 +308,17 @@ make_crypto_key(des3_cbc=Type, String) -> <<K3:8/binary,IVec:8/binary>> = erlang:md5([First|reverse(String)]), {Type,[K1,K2,K3],IVec,8}. +-spec build_module(Chunks) -> {'ok', Binary} when + Chunks :: [{chunkid(), dataB()}], + Binary :: binary(). + +build_module(Chunks0) -> + Chunks = list_to_binary(build_chunks(Chunks0)), + Size = byte_size(Chunks), + 0 = Size rem 4, % Assertion: correct padding? + {ok, <<"FOR1", (Size+4):32, "BEAM", Chunks/binary>>}. + + %% %% Local functions %% @@ -419,12 +430,6 @@ strip_file(File) -> end end. -build_module(Chunks0) -> - Chunks = list_to_binary(build_chunks(Chunks0)), - Size = byte_size(Chunks), - 0 = Size rem 4, % Assertion: correct padding? - {ok, <<"FOR1", (Size+4):32, "BEAM", Chunks/binary>>}. - build_chunks([{Id, Data} | Chunks]) -> BId = list_to_binary(Id), Size = byte_size(Data), diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl index 847161e844..3038a54ee6 100644 --- a/lib/xmerl/src/xmerl_xsd.erl +++ b/lib/xmerl/src/xmerl_xsd.erl @@ -4888,7 +4888,6 @@ mk_EII_Att_QName(AttName,XMLEl,S) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% create_tables(S=#xsd_state{table=undefined}) -> Tid=ets:new(xmerl_schema_tab,[]), - initial_tab_data(Tid), S#xsd_state{table=Tid}; create_tables(S) -> S. @@ -5617,131 +5616,5 @@ format_error(Err) -> %% {shema_el_pathname(SchemaE,Env), %% xml_el_pathname(E)}. -initial_tab_data(Tab) -> - ets:insert(Tab, - binary_to_term( - <<131,108,0,0,0,9,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116, - 101,104,3,100,0,5,115,112,97,99,101,106,100,0,36,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57, - 56,47,110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99,104,101, - 109,97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,5,115,112,97, - 99,101,106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51, - 46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112, - 97,99,101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121, - 112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97, - 109,101,95,108,0,0,0,1,100,0,5,115,112,97,99,101,106,106,106,100,0,5, - 102,97,108,115,101,106,100,0,8,111,112,116,105,111,110,97,108,100,0,9, - 117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105, - 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,2, - 100,0,6,115,99,104,101,109,97,107,0,7,120,109,108,46,120,115,100,104, - 7,100,0,6,115,99,104,101,109,97,100,0,11,117,110,113,117,97,108,105, - 102,105,101,100,100,0,11,117,110,113,117,97,108,105,102,105,101,100, - 100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114, - 103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101, - 106,106,106,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116,101, - 104,3,100,0,4,98,97,115,101,106,100,0,36,104,116,116,112,58,47,47, - 119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47, - 110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99,104,101,109, - 97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,4,98,97,115,101, - 106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111, - 114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99, - 101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101, - 104,3,100,0,6,97,110,121,85,82,73,106,100,0,32,104,116,116,112,58,47, - 47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83, - 99,104,101,109,97,106,100,0,5,102,97,108,115,101,106,100,0,8,111,112, - 116,105,111,110,97,108,100,0,9,117,110,100,101,102,105,110,101,100, - 100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101, - 102,105,110,101,100,104,2,104,2,100,0,14,97,116,116,114,105,98,117, - 116,101,71,114,111,117,112,104,3,100,0,12,115,112,101,99,105,97,108, - 65,116,116,114,115,106,100,0,36,104,116,116,112,58,47,47,119,119,119, - 46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101, - 115,112,97,99,101,104,5,100,0,22,115,99,104,101,109,97,95,97,116,116, - 114,105,98,117,116,101,95,103,114,111,117,112,104,3,100,0,12,115,112, - 101,99,105,97,108,65,116,116,114,115,106,100,0,36,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57, - 56,47,110,97,109,101,115,112,97,99,101,100,0,9,117,110,100,101,102, - 105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,108,0,0, - 0,3,104,2,100,0,9,97,116,116,114,105,98,117,116,101,104,3,100,0,4,98, - 97,115,101,106,106,104,2,100,0,9,97,116,116,114,105,98,117,116,101, - 104,3,100,0,4,108,97,110,103,106,106,104,2,100,0,9,97,116,116,114, - 105,98,117,116,101,104,3,100,0,5,115,112,97,99,101,106,106,106,104, - 2,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0, - 15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0, - 1,100,0,5,115,112,97,99,101,106,106,104,9,100,0,18,115,99,104,101, - 109,97,95,115,105,109,112,108,101,95,116,121,112,101,104,3,100,0,15, - 95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0,1, - 100,0,5,115,112,97,99,101,106,106,108,0,0,0,1,100,0,5,115,112,97,99, - 101,106,104,3,100,0,6,78,67,78,97,109,101,106,100,0,32,104,116,116, - 112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47, - 88,77,76,83,99,104,101,109,97,100,0,5,102,97,108,115,101,106,108,0,0, - 0,1,104,2,100,0,11,101,110,117,109,101,114,97,116,105,111,110,108,0,0, - 0,2,107,0,7,100,101,102,97,117,108,116,107,0,8,112,114,101,115,101, - 114,118,101,106,106,100,0,6,97,116,111,109,105,99,108,0,0,0,1,104,2, - 100,0,11,114,101,115,116,114,105,99,116,105,111,110,104,2,104,3,100, - 0,6,78,67,78,97,109,101,106,100,0,32,104,116,116,112,58,47,47,119, - 119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99, - 104,101,109,97,108,0,0,0,2,104,2,100,0,11,101,110,117,109,101,114, - 97,116,105,111,110,107,0,7,100,101,102,97,117,108,116,104,2,100,0, - 11,101,110,117,109,101,114,97,116,105,111,110,107,0,8,112,114,101, - 115,101,114,118,101,106,106,104,2,104,2,100,0,10,115,105,109,112, - 108,101,84,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110, - 111,95,110,97,109,101,95,108,0,0,0,1,100,0,4,108,97,110,103,106,106, - 104,9,100,0,18,115,99,104,101,109,97,95,115,105,109,112,108,101,95, - 116,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95, - 110,97,109,101,95,108,0,0,0,1,100,0,4,108,97,110,103,106,106,108,0,0, - 0,1,100,0,4,108,97,110,103,106,100,0,9,117,110,100,101,102,105,110, - 101,100,100,0,5,102,97,108,115,101,106,106,100,0,6,97,116,111,109, - 105,99,108,0,0,0,1,104,2,100,0,5,117,110,105,111,110,108,0,0,0,2,104, - 2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0,8,108, - 97,110,103,117,97,103,101,106,100,0,32,104,116,116,112,58,47,47,119, - 119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99,104, - 101,109,97,104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104, - 3,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108, - 0,0,0,2,100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101, - 95,100,0,4,108,97,110,103,106,106,106,106,104,2,104,2,100,0,9,97,116, - 116,114,105,98,117,116,101,104,3,100,0,2,105,100,106,100,0,36,104,116, - 116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47, - 49,57,57,56,47,110,97,109,101,115,112,97,99,101,104,9,100,0,16,115,99, - 104,101,109,97,95,97,116,116,114,105,98,117,116,101,104,3,100,0,2,105, - 100,106,100,0,36,104,116,116,112,58,47,47,119,119,119,46,119,51,46, - 111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97, - 99,101,108,0,0,0,1,104,2,100,0,10,115,105,109,112,108,101,84,121,112, - 101,104,3,100,0,2,73,68,106,100,0,32,104,116,116,112,58,47,47,119,119, - 119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76,83,99,104,101, - 109,97,106,100,0,5,102,97,108,115,101,106,100,0,8,111,112,116,105,111, - 110,97,108,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117, - 110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110, - 101,100,104,2,104,2,100,0,9,97,116,116,114,105,98,117,116,101,104,3, - 100,0,4,108,97,110,103,106,100,0,36,104,116,116,112,58,47,47,119,119, - 119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109, - 101,115,112,97,99,101,104,9,100,0,16,115,99,104,101,109,97,95,97,116, - 116,114,105,98,117,116,101,104,3,100,0,4,108,97,110,103,106,100,0,36, - 104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88, - 77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101,108,0,0,0,1, - 104,2,100,0,10,115,105,109,112,108,101,84,121,112,101,104,3,100,0,15, - 95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,108,0,0,0,1, - 100,0,4,108,97,110,103,106,106,106,100,0,5,102,97,108,115,101,106, - 100,0,8,111,112,116,105,111,110,97,108,100,0,9,117,110,100,101,102, - 105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9, - 117,110,100,101,102,105,110,101,100,104,2,104,2,100,0,10,115,105,109, - 112,108,101,84,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95, - 110,111,95,110,97,109,101,95,108,0,0,0,2,100,0,15,95,120,109,101,114, - 108,95,110,111,95,110,97,109,101,95,100,0,4,108,97,110,103,106,106, - 104,9,100,0,18,115,99,104,101,109,97,95,115,105,109,112,108,101,95, - 116,121,112,101,104,3,100,0,15,95,120,109,101,114,108,95,110,111,95, - 110,97,109,101,95,108,0,0,0,2,100,0,15,95,120,109,101,114,108,95,110, - 111,95,110,97,109,101,95,100,0,4,108,97,110,103,106,106,108,0,0,0,2, - 100,0,15,95,120,109,101,114,108,95,110,111,95,110,97,109,101,95,100, - 0,4,108,97,110,103,106,104,3,100,0,6,115,116,114,105,110,103,106,100, - 0,32,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47, - 50,48,48,49,47,88,77,76,83,99,104,101,109,97,100,0,5,102,97,108,115, - 101,106,108,0,0,0,1,104,2,100,0,11,101,110,117,109,101,114,97,116,105, - 111,110,108,0,0,0,1,106,106,106,100,0,6,97,116,111,109,105,99,108,0,0, - 0,1,104,2,100,0,11,114,101,115,116,114,105,99,116,105,111,110,104,2, - 104,3,100,0,6,115,116,114,105,110,103,106,100,0,32,104,116,116,112,58, - 47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,49,47,88,77,76, - 83,99,104,101,109,97,108,0,0,0,1,104,2,100,0,11,101,110,117,109,101, - 114,97,116,105,111,110,106,106,106,106>>)). - default_namespace_by_convention() -> [{xml,'http://www.w3.org/XML/1998/namespace'}]. diff --git a/lib/xmerl/test/xmerl_xsd_SUITE.erl b/lib/xmerl/test/xmerl_xsd_SUITE.erl index 101fbcd50f..92c8287782 100644 --- a/lib/xmerl/test/xmerl_xsd_SUITE.erl +++ b/lib/xmerl/test/xmerl_xsd_SUITE.erl @@ -41,7 +41,8 @@ groups() -> [{group, primitive_datatypes}, {group, derived_datatypes}]}, {validation_tests, [], - [{group, xmlSchemaPrimerExamples}, + [{group, xmlXsdAndExample}, + {group, xmlSchemaPrimerExamples}, {group, miscXMLexamples}]}, {primitive_datatypes, [], [string, boolean, decimal, float, double, duration, @@ -55,6 +56,8 @@ groups() -> negativeInteger, long, int, short, byte, nonNegativeInteger, unsignedLong, unsignedInt, unsignedShort, unsignedByte, positiveInteger]}, + {xmlXsdAndExample, [], + [xml_xsd, xml_lang_attr]}, {xmlSchemaPrimerExamples, [], [po, po1, po2, ipo, ipo_redefine, '4Q99']}, {miscXMLexamples, [], @@ -863,6 +866,19 @@ compare_duration(_Config) -> ?line indefinite = xmerl_xsd_type:compare_durations("P5M","P153D"), ?line lt = xmerl_xsd_type:compare_durations("P5M","P154D"). +xml_xsd(suite) -> []; +xml_xsd(Config) -> + DataDir = ?config(data_dir, Config), + Options = [{fetch_path, [DataDir]}], + {ok, _} = xmerl_xsd:process_schema("xml.xsd", Options). + +xml_lang_attr(suite) -> []; +xml_lang_attr(Config) -> + DataDir = ?config(data_dir, Config), + {Element, _} = xmerl_scan:file(filename:join([DataDir, "book.xml"])), + Options = [{fetch_path, [DataDir]}], + {ok, Schema} = xmerl_xsd:process_schema("book.xsd", Options), + {Element, _} = xmerl_xsd:validate(Element, Schema). po(suite) -> []; po(Config) -> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml new file mode 100644 index 0000000000..17d7ceffee --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<book title="Title" xml:lang="EN"> + <author>Author1</author> + <author>Author2</author> +</book> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd new file mode 100644 index 0000000000..830951ec1b --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/book.xsd @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/> + <xs:element name="book"> + <xs:complexType> + <xs:sequence> + <xs:element name="author" type="xs:string" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="title" type="xs:string"/> + <xs:attribute ref="xml:lang"/> + </xs:complexType> + </xs:element> +</xs:schema> diff --git a/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd b/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd new file mode 100644 index 0000000000..aea7d0db0a --- /dev/null +++ b/lib/xmerl/test/xmerl_xsd_SUITE_data/xml.xsd @@ -0,0 +1,287 @@ +<?xml version='1.0'?> +<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?> +<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns ="http://www.w3.org/1999/xhtml" + xml:lang="en"> + + <xs:annotation> + <xs:documentation> + <div> + <h1>About the XML namespace</h1> + + <div class="bodytext"> + <p> + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + </p> + <p> + See <a href="http://www.w3.org/XML/1998/namespace.html"> + http://www.w3.org/XML/1998/namespace.html</a> and + <a href="http://www.w3.org/TR/REC-xml"> + http://www.w3.org/TR/REC-xml</a> for information + about this namespace. + </p> + <p> + Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. + </p> + <p> + See further below in this document for more information about <a + href="#usage">how to refer to this schema document from your own + XSD schema documents</a> and about <a href="#nsversioning">the + namespace-versioning policy governing this schema document</a>. + </p> + </div> + </div> + </xs:documentation> + </xs:annotation> + + <xs:attribute name="lang"> + <xs:annotation> + <xs:documentation> + <div> + + <h3>lang (as an attribute name)</h3> + <p> + denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.</p> + + </div> + <div> + <h4>Notes</h4> + <p> + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. + </p> + <p> + See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt"> + http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a> + and the IANA language subtag registry at + <a href="http://www.iana.org/assignments/language-subtag-registry"> + http://www.iana.org/assignments/language-subtag-registry</a> + for further information. + </p> + <p> + The union allows for the 'un-declaration' of xml:lang with + the empty string. + </p> + </div> + </xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:union memberTypes="xs:language"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value=""/> + </xs:restriction> + </xs:simpleType> + </xs:union> + </xs:simpleType> + </xs:attribute> + + <xs:attribute name="space"> + <xs:annotation> + <xs:documentation> + <div> + + <h3>space (as an attribute name)</h3> + <p> + denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.</p> + + </div> + </xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:NCName"> + <xs:enumeration value="default"/> + <xs:enumeration value="preserve"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + + <xs:attribute name="base" type="xs:anyURI"> <xs:annotation> + <xs:documentation> + <div> + + <h3>base (as an attribute name)</h3> + <p> + denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.</p> + + <p> + See <a + href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a> + for information about this attribute. + </p> + </div> + </xs:documentation> + </xs:annotation> + </xs:attribute> + + <xs:attribute name="id" type="xs:ID"> + <xs:annotation> + <xs:documentation> + <div> + + <h3>id (as an attribute name)</h3> + <p> + denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.</p> + + <p> + See <a + href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a> + for information about this attribute. + </p> + </div> + </xs:documentation> + </xs:annotation> + </xs:attribute> + + <xs:attributeGroup name="specialAttrs"> + <xs:attribute ref="xml:base"/> + <xs:attribute ref="xml:lang"/> + <xs:attribute ref="xml:space"/> + <xs:attribute ref="xml:id"/> + </xs:attributeGroup> + + <xs:annotation> + <xs:documentation> + <div> + + <h3>Father (in any context at all)</h3> + + <div class="bodytext"> + <p> + denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + </p> + <blockquote> + <p> + In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". + </p> + </blockquote> + </div> + </div> + </xs:documentation> + </xs:annotation> + + <xs:annotation> + <xs:documentation> + <div xml:id="usage" id="usage"> + <h2><a name="usage">About this schema document</a></h2> + + <div class="bodytext"> + <p> + This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow <code>xml:base</code>, + <code>xml:lang</code>, <code>xml:space</code> or + <code>xml:id</code> attributes on elements they define. + </p> + <p> + To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: + </p> + <pre> + <schema . . .> + . . . + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2001/xml.xsd"/> + </pre> + <p> + or + </p> + <pre> + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2009/01/xml.xsd"/> + </pre> + <p> + Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. + </p> + <pre> + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + </pre> + <p> + will define a type which will schema-validate an instance element + with any of those attributes. + </p> + </div> + </div> + </xs:documentation> + </xs:annotation> + + <xs:annotation> + <xs:documentation> + <div id="nsversioning" xml:id="nsversioning"> + <h2><a name="nsversioning">Versioning policy for this schema document</a></h2> + <div class="bodytext"> + <p> + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + <a href="http://www.w3.org/2009/01/xml.xsd"> + http://www.w3.org/2009/01/xml.xsd</a>. + </p> + <p> + At the date of issue it can also be found at + <a href="http://www.w3.org/2001/xml.xsd"> + http://www.w3.org/2001/xml.xsd</a>. + </p> + <p> + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at <a href="http://www.w3.org/2001/xml.xsd"> + http://www.w3.org/2001/xml.xsd + </a> + will change accordingly; the version at + <a href="http://www.w3.org/2009/01/xml.xsd"> + http://www.w3.org/2009/01/xml.xsd + </a> + will not change. + </p> + <p> + Previous dated (and unchanging) versions of this schema + document are at: + </p> + <ul> + <li><a href="http://www.w3.org/2009/01/xml.xsd"> + http://www.w3.org/2009/01/xml.xsd</a></li> + <li><a href="http://www.w3.org/2007/08/xml.xsd"> + http://www.w3.org/2007/08/xml.xsd</a></li> + <li><a href="http://www.w3.org/2004/10/xml.xsd"> + http://www.w3.org/2004/10/xml.xsd</a></li> + <li><a href="http://www.w3.org/2001/03/xml.xsd"> + http://www.w3.org/2001/03/xml.xsd</a></li> + </ul> + </div> + </div> + </xs:documentation> + </xs:annotation> + +</xs:schema> + @@ -1443,13 +1443,13 @@ case "$1" in do_debuginfo_win32 "$2";; env_win32) if [ x"$2" = x"x64" -o x"$2" = x"amd64" ]; then - if [ -x /usr/bin/msysinfo ]; then + if [ -x /usr/bin/msys-?.0.dll ]; then echo_env_msys64 else echo_env_win64 fi else - if [ -x /usr/bin/msysinfo ]; then + if [ -x /usr/bin/msys-?.0.dll ]; then echo_env_msys32 else echo_env_win32 diff --git a/system/doc/efficiency_guide/binaryhandling.xml b/system/doc/efficiency_guide/binaryhandling.xml index 51f8c4ebf0..0964b759d8 100644 --- a/system/doc/efficiency_guide/binaryhandling.xml +++ b/system/doc/efficiency_guide/binaryhandling.xml @@ -190,15 +190,15 @@ Bin4 = <<Bin1/binary,17>>, %% 5 !!! its size set to the size of the data stored in the binary, while the binary object has extra space allocated. The size of the binary object is either twice the - size of <c>Bin0</c> or 256, whichever is larger. In this case + size of <c>Bin1</c> or 256, whichever is larger. In this case it is 256.</item> <item>Line 3 is more interesting. <c>Bin1</c> <em>has</em> been used in an append operation, - and it has 255 bytes of unused storage at the end, so the 3 new + and it has 252 bytes of unused storage at the end, so the 3 new bytes are stored there.</item> - <item>Line 4. The same applies here. There are 252 bytes left, + <item>Line 4. The same applies here. There are 249 bytes left, so there is no problem storing another 3 bytes.</item> <item>Line 5. Here, something <em>interesting</em> happens. Notice |