aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c10
-rw-r--r--lib/asn1/doc/src/Makefile1
-rw-r--r--lib/asn1/doc/src/notes.xml22
-rw-r--r--lib/asn1/src/asn1ct_check.erl2
-rw-r--r--lib/asn1/test/asn1_SUITE.erl43
-rw-r--r--lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn2
-rw-r--r--lib/common_test/doc/src/Makefile1
-rw-r--r--lib/common_test/doc/src/ct.xml2
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml2
-rw-r--r--lib/common_test/doc/src/notes.xml10
-rw-r--r--lib/common_test/src/ct_framework.erl2
-rw-r--r--lib/common_test/src/ct_release_test.erl20
-rw-r--r--lib/common_test/src/ct_telnet.erl2
-rw-r--r--lib/common_test/src/ct_util.erl5
-rw-r--r--lib/common_test/src/cth_log_redirect.erl16
-rw-r--r--lib/common_test/src/test_server_ctrl.erl4
-rw-r--r--lib/common_test/test/ct_auto_compile_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl4
-rw-r--r--lib/common_test/test/test_server_SUITE.erl4
-rw-r--r--lib/common_test/test/test_server_test_lib.erl2
-rw-r--r--lib/compiler/doc/src/Makefile1
-rw-r--r--lib/compiler/doc/src/notes.xml79
-rw-r--r--lib/compiler/src/beam_bsm.erl13
-rw-r--r--lib/compiler/src/beam_jump.erl76
-rw-r--r--lib/compiler/src/beam_type.erl2
-rw-r--r--lib/compiler/src/beam_utils.erl13
-rw-r--r--lib/compiler/src/beam_validator.erl34
-rw-r--r--lib/compiler/src/compile.erl29
-rw-r--r--lib/compiler/src/erl_bifs.erl1
-rwxr-xr-xlib/compiler/src/genop.tab3
-rw-r--r--lib/compiler/src/sys_core_fold.erl136
-rw-r--r--lib/compiler/src/v3_codegen.erl5
-rw-r--r--lib/compiler/src/v3_core.erl36
-rw-r--r--lib/compiler/test/andor_SUITE.erl2
-rw-r--r--lib/compiler/test/apply_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_block_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_except_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_jump_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_reorder_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl34
-rw-r--r--lib/compiler/test/beam_utils_SUITE.erl50
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl2
-rw-r--r--lib/compiler/test/bif_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl13
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl4
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl6
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl35
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl2
-rw-r--r--lib/compiler/test/compilation_SUITE.erl2
-rw-r--r--lib/compiler/test/compile_SUITE.erl23
-rw-r--r--lib/compiler/test/core_SUITE.erl7
-rw-r--r--lib/compiler/test/core_SUITE_data/fun_letrec_effect.core25
-rw-r--r--lib/compiler/test/core_alias_SUITE.erl2
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl43
-rw-r--r--lib/compiler/test/error_SUITE.erl2
-rw-r--r--lib/compiler/test/float_SUITE.erl2
-rw-r--r--lib/compiler/test/fun_SUITE.erl2
-rw-r--r--lib/compiler/test/guard_SUITE.erl2
-rw-r--r--lib/compiler/test/inline_SUITE.erl2
-rw-r--r--lib/compiler/test/lc_SUITE.erl2
-rw-r--r--lib/compiler/test/map_SUITE.erl61
-rw-r--r--lib/compiler/test/match_SUITE.erl2
-rw-r--r--lib/compiler/test/misc_SUITE.erl2
-rw-r--r--lib/compiler/test/overridden_bif_SUITE.erl2
-rw-r--r--lib/compiler/test/receive_SUITE.erl79
-rw-r--r--lib/compiler/test/record_SUITE.erl2
-rw-r--r--lib/compiler/test/regressions_SUITE.erl19
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl2
-rw-r--r--lib/compiler/test/warnings_SUITE.erl2
-rw-r--r--lib/compiler/test/z_SUITE.erl2
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/crypto/c_src/crypto.c95
-rw-r--r--lib/crypto/doc/src/Makefile1
-rw-r--r--lib/crypto/doc/src/crypto.xml4
-rw-r--r--lib/crypto/doc/src/engine_keys.xml2
-rw-r--r--lib/crypto/doc/src/notes.xml32
-rw-r--r--lib/crypto/src/crypto.erl10
-rw-r--r--lib/crypto/src/crypto_ec_curves.erl36
-rw-r--r--lib/crypto/test/crypto_SUITE.erl155
-rw-r--r--lib/crypto/test/engine_SUITE.erl2
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/Makefile1
-rw-r--r--lib/debugger/src/dbg_icmd.erl2
-rw-r--r--lib/dialyzer/doc/src/Makefile1
-rw-r--r--lib/dialyzer/src/typer.erl2
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl4
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl4
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/maps_sum2
-rw-r--r--lib/diameter/doc/src/Makefile1
-rw-r--r--lib/edoc/doc/src/Makefile1
-rw-r--r--lib/eldap/doc/src/Makefile1
-rw-r--r--lib/erl_docgen/doc/src/Makefile1
-rw-r--r--lib/erl_docgen/src/docgen_edoc_xml_cb.erl2
-rw-r--r--lib/erl_interface/doc/src/Makefile1
-rw-r--r--lib/erl_interface/doc/src/notes.xml18
-rw-r--r--lib/erl_interface/src/INSTALL4
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c44
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c3
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl9
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c11
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl16
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c12
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl20
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c5
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl6
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c1
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl22
-rw-r--r--lib/erl_interface/test/ei_format_SUITE.erl12
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl12
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl28
-rw-r--r--lib/erl_interface/test/erl_connect_SUITE.erl10
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE.erl78
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE.erl13
-rw-r--r--lib/erl_interface/test/erl_format_SUITE.erl10
-rw-r--r--lib/erl_interface/test/erl_global_SUITE.erl9
-rw-r--r--lib/erl_interface/test/erl_match_SUITE.erl7
-rw-r--r--lib/erl_interface/test/port_call_SUITE.erl6
-rw-r--r--lib/erl_interface/test/runner.erl56
-rw-r--r--lib/et/doc/src/Makefile1
-rw-r--r--lib/et/doc/src/et_collector.xml8
-rw-r--r--lib/et/doc/src/et_selector.xml4
-rw-r--r--lib/et/src/et_collector.erl2
-rw-r--r--lib/eunit/doc/src/Makefile1
-rw-r--r--lib/ftp/doc/src/Makefile1
-rw-r--r--lib/ftp/doc/src/ftp.xml12
-rw-r--r--lib/ftp/src/ftp.erl124
-rw-r--r--lib/hipe/doc/src/Makefile1
-rw-r--r--lib/hipe/doc/src/hipe_app.xml4
-rw-r--r--lib/hipe/icode/hipe_icode_range.erl2
-rw-r--r--lib/hipe/rtl/hipe_icode2rtl.erl2
-rw-r--r--lib/hipe/rtl/hipe_rtl_arith.inc4
-rw-r--r--lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl6
-rw-r--r--lib/inets/doc/src/Makefile1
-rw-r--r--lib/inets/doc/src/httpd.xml2
-rw-r--r--lib/inets/doc/src/mod_security.xml3
-rw-r--r--lib/inets/doc/src/notes.xml55
-rw-r--r--lib/inets/doc/src/notes_history.xml4
-rw-r--r--lib/inets/src/http_client/httpc_cookie.erl2
-rw-r--r--lib/inets/src/http_client/httpc_response.erl41
-rw-r--r--lib/inets/src/http_server/httpd_file.erl3
-rw-r--r--lib/inets/src/http_server/httpd_response.erl8
-rw-r--r--lib/inets/test/http_format_SUITE.erl2
-rw-r--r--lib/inets/test/httpc_SUITE.erl98
-rw-r--r--lib/inets/test/httpc_proxy_SUITE.erl2
-rw-r--r--lib/inets/test/httpd_SUITE.erl68
-rw-r--r--lib/jinterface/doc/src/Makefile1
-rw-r--r--lib/jinterface/doc/src/notes.xml2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java12
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java4
-rw-r--r--lib/kernel/doc/src/.gitignore1
-rw-r--r--lib/kernel/doc/src/Makefile15
-rw-r--r--lib/kernel/doc/src/code.xml4
-rw-r--r--lib/kernel/doc/src/inet.xml19
-rw-r--r--lib/kernel/doc/src/kernel_app.xml39
-rw-r--r--lib/kernel/doc/src/logger.xml170
-rw-r--r--lib/kernel/doc/src/logger_arch.diabin0 -> 2527 bytes
-rw-r--r--lib/kernel/doc/src/logger_arch.pngbin32187 -> 117205 bytes
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml22
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml29
-rw-r--r--lib/kernel/doc/src/net_kernel.xml6
-rw-r--r--lib/kernel/doc/src/notes.xml36
-rw-r--r--lib/kernel/include/logger.hrl4
-rw-r--r--lib/kernel/src/Makefile3
-rw-r--r--lib/kernel/src/error_logger.erl15
-rw-r--r--lib/kernel/src/erts_debug.erl58
-rw-r--r--lib/kernel/src/inet_config.erl2
-rw-r--r--lib/kernel/src/inet_dns.erl2
-rw-r--r--lib/kernel/src/kernel.app.src2
-rw-r--r--lib/kernel/src/logger.erl82
-rw-r--r--lib/kernel/src/logger_disk_log_h.erl8
-rw-r--r--lib/kernel/src/logger_formatter.erl200
-rw-r--r--lib/kernel/src/logger_h_common.erl13
-rw-r--r--lib/kernel/src/logger_handler_watcher.erl113
-rw-r--r--lib/kernel/src/logger_server.erl4
-rw-r--r--lib/kernel/src/logger_std_h.erl8
-rw-r--r--lib/kernel/src/logger_sup.erl6
-rw-r--r--lib/kernel/src/net_kernel.erl2
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl8
-rw-r--r--lib/kernel/test/file_SUITE.erl4
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl12
-rw-r--r--lib/kernel/test/inet_SUITE.erl2
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl2
-rw-r--r--lib/kernel/test/logger_SUITE.erl78
-rw-r--r--lib/kernel/test/logger_disk_log_h_SUITE.erl29
-rw-r--r--lib/kernel/test/logger_env_var_SUITE.erl19
-rw-r--r--lib/kernel/test/logger_formatter_SUITE.erl94
-rw-r--r--lib/kernel/test/logger_std_h_SUITE.erl31
-rw-r--r--lib/kernel/test/seq_trace_SUITE.erl18
-rw-r--r--lib/megaco/doc/src/Makefile1
-rw-r--r--lib/mnesia/doc/src/Makefile1
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml2
-rw-r--r--lib/mnesia/doc/src/notes.xml28
-rw-r--r--lib/mnesia/src/mnesia.erl22
-rw-r--r--lib/mnesia/src/mnesia_controller.erl30
-rw-r--r--lib/mnesia/src/mnesia_lib.erl2
-rw-r--r--lib/mnesia/src/mnesia_loader.erl8
-rw-r--r--lib/mnesia/src/mnesia_tm.erl2
-rw-r--r--lib/mnesia/test/mnesia_durability_test.erl107
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl47
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl11
-rw-r--r--lib/observer/doc/src/Makefile1
-rw-r--r--lib/observer/src/cdv_bin_cb.erl4
-rw-r--r--lib/observer/src/cdv_term_cb.erl2
-rw-r--r--lib/observer/src/observer_tv_wx.erl4
-rw-r--r--lib/observer/src/observer_wx.erl2
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE_data/old_format.dump8
-rw-r--r--lib/observer/test/observer_SUITE.erl2
-rw-r--r--lib/odbc/doc/src/Makefile1
-rw-r--r--lib/odbc/doc/src/databases.xml2
-rw-r--r--lib/odbc/doc/src/error_handling.xml2
-rw-r--r--lib/odbc/doc/src/getting_started.xml2
-rw-r--r--lib/odbc/doc/src/notes_history.xml4
-rw-r--r--lib/odbc/doc/src/odbc.xml2
-rw-r--r--lib/odbc/test/odbc_connect_SUITE.erl2
-rw-r--r--lib/os_mon/doc/src/Makefile1
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl11
-rw-r--r--lib/otp_mibs/doc/src/Makefile1
-rw-r--r--lib/parsetools/doc/src/Makefile1
-rw-r--r--lib/public_key/doc/src/Makefile1
-rw-r--r--lib/public_key/doc/src/notes.xml20
-rw-r--r--lib/public_key/doc/src/public_key.xml4
-rw-r--r--lib/public_key/priv/moduli66
-rw-r--r--lib/public_key/src/pubkey_moduli.hrl134
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/Makefile1
-rw-r--r--lib/reltool/doc/src/reltool.xml2
-rw-r--r--lib/reltool/src/reltool_server.erl2
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl4
-rw-r--r--lib/runtime_tools/doc/src/Makefile1
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml4
-rw-r--r--lib/runtime_tools/src/observer_backend.erl2
-rw-r--r--lib/runtime_tools/src/system_information.erl1
-rw-r--r--lib/sasl/doc/src/Makefile1
-rw-r--r--lib/sasl/src/rb.erl2
-rw-r--r--lib/sasl/src/release_handler.erl4
-rw-r--r--lib/sasl/src/release_handler_1.erl2
-rw-r--r--lib/sasl/test/installer.erl2
-rw-r--r--lib/sasl/test/rb_SUITE.erl2
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl81
-rw-r--r--lib/sasl/test/systools_SUITE.erl2
-rw-r--r--lib/snmp/doc/src/Makefile1
-rw-r--r--lib/snmp/src/agent/snmpa_set_lib.erl6
-rw-r--r--lib/snmp/src/agent/snmpa_trap.erl4
-rw-r--r--lib/snmp/test/test-mibs/ALARM-MIB.mib2
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-TC.mib4
-rw-r--r--lib/ssh/doc/src/Makefile1
-rw-r--r--lib/ssh/doc/src/notes.xml30
-rw-r--r--lib/ssh/doc/src/ssh.xml2
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml8
-rw-r--r--lib/ssh/src/ssh.hrl25
-rw-r--r--lib/ssh/src/ssh_dbg.erl116
-rw-r--r--lib/ssh/src/ssh_sftp.erl13
-rw-r--r--lib/ssh/src/ssh_sftpd.erl6
-rw-r--r--lib/ssh/src/ssh_transport.erl31
-rw-r--r--lib/ssh/src/ssh_xfer.erl2
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE.erl68
-rw-r--r--lib/ssh/vsn.mk1
-rw-r--r--lib/ssl/doc/src/Makefile1
-rw-r--r--lib/ssl/doc/src/notes.xml56
-rw-r--r--lib/ssl/doc/src/ssl.xml47
-rw-r--r--lib/ssl/doc/src/ssl_distribution.xml2
-rw-r--r--lib/ssl/examples/src/client_server.erl12
-rw-r--r--lib/ssl/src/Makefile5
-rw-r--r--lib/ssl/src/dtls_connection.erl19
-rw-r--r--lib/ssl/src/dtls_packet_demux.erl5
-rw-r--r--lib/ssl/src/inet_tls_dist.erl23
-rw-r--r--lib/ssl/src/ssl.app.src2
-rw-r--r--lib/ssl/src/ssl.erl88
-rw-r--r--lib/ssl/src/ssl_app.erl17
-rw-r--r--lib/ssl/src/ssl_certificate.erl2
-rw-r--r--lib/ssl/src/ssl_cipher.erl20
-rw-r--r--lib/ssl/src/ssl_config.erl6
-rw-r--r--lib/ssl/src/ssl_connection.erl186
-rw-r--r--lib/ssl/src/ssl_crl_hash_dir.erl5
-rw-r--r--lib/ssl/src/ssl_handshake.erl169
-rw-r--r--lib/ssl/src/ssl_handshake.hrl13
-rw-r--r--lib/ssl/src/ssl_internal.hrl34
-rw-r--r--lib/ssl/src/ssl_logger.erl349
-rw-r--r--lib/ssl/src/ssl_manager.erl14
-rw-r--r--lib/ssl/src/ssl_pem_cache.erl12
-rw-r--r--lib/ssl/src/ssl_pkix_db.erl20
-rw-r--r--lib/ssl/src/ssl_record.hrl2
-rw-r--r--lib/ssl/src/tls_connection.erl73
-rw-r--r--lib/ssl/src/tls_handshake.erl150
-rw-r--r--lib/ssl/src/tls_record.erl65
-rw-r--r--lib/ssl/src/tls_v1.erl18
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl54
-rw-r--r--lib/ssl/test/ssl_ECC_openssl_SUITE.erl17
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl204
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl4
-rw-r--r--lib/ssl/test/ssl_engine_SUITE.erl15
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl45
-rw-r--r--lib/ssl/test/ssl_test_lib.erl76
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/Makefile1
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml8
-rw-r--r--lib/stdlib/doc/src/maps.xml34
-rw-r--r--lib/stdlib/doc/src/notes.xml23
-rw-r--r--lib/stdlib/include/assert.hrl6
-rw-r--r--lib/stdlib/src/beam_lib.erl23
-rw-r--r--lib/stdlib/src/erl_eval.erl15
-rw-r--r--lib/stdlib/src/erl_internal.erl2
-rw-r--r--lib/stdlib/src/erl_parse.yrl2
-rw-r--r--lib/stdlib/src/erl_posix_msg.erl4
-rw-r--r--lib/stdlib/src/erl_pp.erl4
-rw-r--r--lib/stdlib/src/io_lib.erl49
-rw-r--r--lib/stdlib/src/io_lib_format.erl8
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl12
-rw-r--r--lib/stdlib/src/maps.erl157
-rw-r--r--lib/stdlib/src/proc_lib.erl128
-rw-r--r--lib/stdlib/src/rand.erl2
-rw-r--r--lib/stdlib/src/uri_string.erl23
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl32
-rw-r--r--lib/stdlib/test/epp_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl2
-rw-r--r--lib/stdlib/test/ets_SUITE.erl35
-rw-r--r--lib/stdlib/test/io_SUITE.erl18
-rw-r--r--lib/stdlib/test/lists_SUITE.erl2
-rw-r--r--lib/stdlib/test/stdlib.spec2
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE.erl67
-rw-r--r--lib/stdlib/test/uri_string_SUITE.erl10
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/Makefile1
-rw-r--r--lib/syntax_tools/doc/src/notes.xml33
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl41
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl2
-rw-r--r--lib/syntax_tools/src/igor.erl2
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl1
-rw-r--r--lib/tftp/doc/src/Makefile1
-rw-r--r--lib/tftp/doc/src/tftp.xml6
-rw-r--r--lib/tools/doc/src/Makefile1
-rw-r--r--lib/tools/doc/src/cover.xml6
-rw-r--r--lib/tools/doc/src/instrument.xml13
-rw-r--r--lib/tools/emacs/erlang.el14
-rw-r--r--lib/tools/priv/styles.css91
-rw-r--r--lib/tools/src/Makefile5
-rw-r--r--lib/tools/src/cover.erl111
-rw-r--r--lib/tools/test/instrument_SUITE.erl35
-rw-r--r--lib/tools/test/xref_SUITE.erl6
-rw-r--r--lib/wx/c_src/wxe_driver.c165
-rw-r--r--lib/wx/c_src/wxe_driver.h2
-rw-r--r--lib/wx/c_src/wxe_main.cpp15
-rw-r--r--lib/wx/doc/overview.edoc2
-rw-r--r--lib/wx/doc/src/Makefile3
-rw-r--r--lib/wx/examples/demo/ex_graphicsContext.erl2
-rw-r--r--lib/wx/test/wx_event_SUITE.erl4
-rwxr-xr-xlib/wx/test/wxt4
-rw-r--r--lib/xmerl/doc/src/Makefile1
-rw-r--r--lib/xmerl/src/xmerl_scan.erl2
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml26
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml26
357 files changed, 5567 insertions, 1993 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 0053238826..cdb3f3f3dc 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -58,7 +58,7 @@ else
SUB_DIRECTORIES = hipe parsetools asn1/src
else
ifdef TERTIARY_BOOTSTRAP
- SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools wx
+ SUB_DIRECTORIES = snmp sasl jinterface syntax_tools wx
else
ifdef DOC_BOOTSTRAP
SUB_DIRECTORIES = xmerl edoc erl_docgen
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index d5aaadb89b..797be6d4f8 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -949,6 +949,12 @@ static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *
unsigned char *tmp_out_buff;
ERL_NIF_TERM term = 0, curr_head = 0;
+ /* Recursion depth limitation, borrow a signed int: maybe_ret */
+ maybe_ret = (int) (ErlNifSInt) ((char *)value - (char *)ib_index);
+ maybe_ret = maybe_ret < 0 ? -maybe_ret : maybe_ret;
+ if (maybe_ret >= sizeof(void *) * 8192) /* 8 k pointer words */
+ return ASN1_ERROR;
+
if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
len = in_buf[*ib_index];
} else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH) {
@@ -993,7 +999,7 @@ static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *
while (*ib_index < end_index) {
if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index,
- in_buf_len)) <= ASN1_ERROR
+ *ib_index + len)) <= ASN1_ERROR
)
return maybe_ret;
curr_head = enif_make_list_cell(env, term, curr_head);
diff --git a/lib/asn1/doc/src/Makefile b/lib/asn1/doc/src/Makefile
index f200c4aae2..9c0d865884 100644
--- a/lib/asn1/doc/src/Makefile
+++ b/lib/asn1/doc/src/Makefile
@@ -107,6 +107,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(GEN_XML) errs core *~
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 860cf4d22d..c86fa79c2c 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -47,6 +47,28 @@
</section>
+<section><title>Asn1 5.0.5.1</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>A bug in ASN.1 BER decoding has been fixed. When
+ decoding a recursively enclosed term the length was not
+ propagated to that term decoding, so if the length of the
+ enclosed term was longer than the enclosing that error
+ was not dectected</p> <p>A hard coded C stack limitation
+ for decoding recursive ASN.1 terms has been introduced.
+ This is currently set to 8 kWords giving a nesting depth
+ of about 1000 levels. Deeper terms can not be decoded,
+ which should not be much of a real world limitation.</p>
+ <p>
+ Own Id: OTP-14440 Aux Id: ERIERL-220 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index 321980e5e4..9ec0d93e93 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -5770,7 +5770,7 @@ format_error({missing_ocft,Component}) ->
format_error(multiple_uniqs) ->
"implementation limitation: only one UNIQUE field is allowed in CLASS";
format_error({namelist_redefinition,Name}) ->
- io_lib:format("the name '~s' can not be redefined", [Name]);
+ io_lib:format("the name '~s' cannot be redefined", [Name]);
format_error({param_bad_type, Ref}) ->
io_lib:format("'~p' is not a parameterized type", [Ref]);
format_error(param_wrong_number_of_arguments) ->
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 7b669c1c2c..5506923341 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -132,7 +132,8 @@ groups() ->
testSeq2738,
% Uses 'Constructed'
{group, [], [constructed,
- ber_decode_error]},
+ ber_decode_error,
+ otp_14440]},
testSeqSetIndefinite,
testChoiceIndefinite,
per_open_type,
@@ -736,6 +737,36 @@ ber_decode_error(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
ber_decode_error:run(Opts).
+otp_14440(_Config) ->
+ Args = " -pa \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
+ {ok,N} = slave:start(hostname(), otp_14440, Args),
+ Result = rpc:call(N, ?MODULE, otp_14440_decode, []),
+ io:format("Decode result = ~p~n", [Result]),
+ case Result of
+ {exit,{error,{asn1,{invalid_value,5}}}} ->
+ ok = slave:stop(N);
+ %% We get this if stack depth limit kicks in:
+ {exit,{error,{asn1,{unknown,_}}}} ->
+ ok = slave:stop(N);
+ _ ->
+ _ = slave:stop(N),
+ ?t:fail(Result)
+ end.
+%%
+otp_14440_decode() ->
+ Data =
+ iolist_to_binary(
+ lists:duplicate(
+ 32, list_to_binary(lists:duplicate(1024, 16#7f)))),
+ try asn1rt_nif:decode_ber_tlv(Data) of
+ Result ->
+ {unexpected_return,Result}
+ catch
+ Class:Reason ->
+ {Class,Reason}
+ end.
+
+
h323test(Config) -> test(Config, fun h323test/3).
h323test(Config, Rule, Opts) ->
Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES",
@@ -1350,7 +1381,7 @@ xref_export_all(_Config) ->
{ok,_} = xref:q(S, Def),
{ok,Unused} = xref:q(S, "X - Called - range (closure E | Called)"),
xref:stop(S),
- case Unused of
+ case Unused -- [{?MODULE,otp_14440_decode,0}] of
[] ->
ok;
[_|_] ->
@@ -1385,3 +1416,11 @@ all_called_1([F|T]) when is_atom(F) ->
L ++ all_called_1(T);
all_called_1([]) ->
[].
+
+hostname() ->
+ hostname(atom_to_list(node())).
+
+hostname([$@ | Hostname]) ->
+ list_to_atom(Hostname);
+hostname([_C | Cs]) ->
+ hostname(Cs).
diff --git a/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn b/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn
index ff0361f5c5..fb092f3f9c 100644
--- a/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn
+++ b/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn
@@ -1152,7 +1152,7 @@ FilteringCriteria ::= CHOICE {
-- In case calledAddressValue is specified, the numbers to be filtered are from calledAddressValue
-- up to and including calledAddressValue + maximumNumberOfCounters-1.
--- The last two digits of calledAddressvalue can not exceed 100-maximumNumberOfCounters.
+-- The last two digits of calledAddressvalue cannot exceed 100-maximumNumberOfCounters.
FilteringTimeOut ::= CHOICE {
duration [0] Duration,
stopTime [1] DateAndTime
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile
index 293ef591cb..4d6161d3ae 100644
--- a/lib/common_test/doc/src/Makefile
+++ b/lib/common_test/doc/src/Makefile
@@ -140,6 +140,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
diff --git a/lib/common_test/doc/src/ct.xml b/lib/common_test/doc/src/ct.xml
index b51dee266b..c0380c4142 100644
--- a/lib/common_test/doc/src/ct.xml
+++ b/lib/common_test/doc/src/ct.xml
@@ -1522,7 +1522,7 @@
<v>Hours = integer()</v>
<v>Mins = integer()</v>
<v>Secs = integer()</v>
- <v>Millisecs = integer() | float()</v>
+ <v>Millisecs = integer()</v>
<v>Func = {M, F, A} | function()</v>
<v>M = atom()</v>
<v>F = atom()</v>
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index 954be0ffba..2f853d133d 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -368,7 +368,7 @@
<seealso marker="common_test#Module:end_per_testcase-2"><c>end_per_testcase</c></seealso>
instead.</p>
- <p>This function can not change the result of the test case by returning skip or fail
+ <p>This function cannot change the result of the test case by returning skip or fail
tuples, but it may insert items in <c>Config</c> that can be read in
<c>end_per_testcase/2</c> or in <c>post_end_per_testcase/5</c>.</p>
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index c8005d8f79..df22896b27 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -2089,7 +2089,7 @@
ct_netconfc:close_session sometimes returned
{error,closed} because the ssh connection was closed
(from the server side) before the rpc-reply was received
- by the client. This is normal and can not be helped. It
+ by the client. This is normal and cannot be helped. It
has been corrected so the return will be 'ok' in this
case. Other error situations will still give
{error,Reason}.</p>
@@ -2103,7 +2103,7 @@
{error,{process_down,Pid,normal}} because the ssh
connection was closed (from the server side) before the
rpc-reply was received by the client. This is normal and
- can not be helped. It has been corrected so the return
+ cannot be helped. It has been corrected so the return
will be 'ok' in this situation.</p>
<p>
Own Id: OTP-10570</p>
@@ -2755,8 +2755,8 @@
The info function for <c>init/end_per_suite(Config)</c>
is <c>init/end_per_suite()</c>, and for
<c>init/end_per_group(GroupName,Config)</c> it's
- <c>init/end_per_group(GroupName)</c>. Info functions can
- not be used with <c>init/end_per_testcase(TestCase,
+ <c>init/end_per_group(GroupName)</c>. Info functions
+ cannot be used with <c>init/end_per_testcase(TestCase,
Config)</c>, since these configuration functions execute
on the test case process and will use the same properties
as the test case (i.e. properties set by the test case
@@ -3840,7 +3840,7 @@
If the Erlang runtime system was started without access
to an erlang shell (e.g. -noshell), compilation errors
would cause a crash in the Common Test application.
- Without access to a shell, Common Test can not prompt the
+ Without access to a shell, Common Test cannot prompt the
user to choose to continue or abort the test session, but
must assume that the session should proceed.</p>
<p>
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 134ae0e1cc..7e98e6395f 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -1168,7 +1168,7 @@ get_all(Mod, ConfTests) ->
case code:which(Mod) of
non_existing ->
list_to_atom(atom_to_list(Mod)++
- " can not be compiled or loaded");
+ " cannot be compiled or loaded");
_ ->
list_to_atom(atom_to_list(Mod)++":all/0 is missing")
end,
diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl
index 60d17f43dc..ac3dcab7c9 100644
--- a/lib/common_test/src/ct_release_test.erl
+++ b/lib/common_test/src/ct_release_test.erl
@@ -152,10 +152,10 @@
%% returned configuration must therefore also be returned from
%% the calling `init_per_*'.
%%
-%% If the initialization fails, e.g. if a required release can
-%% not be found, the function returns `{skip,Reason}'. In
+%% If the initialization fails, e.g. if a required release
+%% cannot be found, the function returns `{skip,Reason}'. In
%% this case the other test support functions in this mudule
-%% can not be used.
+%% cannot be used.
%%
%% Example:
%%
@@ -426,7 +426,7 @@ init_upgrade_test(Level) ->
case OldRel of
false ->
ct:log("Release ~tp is not available."
- " Upgrade on '~p' level can not be tested.",
+ " Upgrade on '~p' level cannot be tested.",
[FromVsn,Level]),
undefined;
_ ->
@@ -528,7 +528,7 @@ target_system(Apps,CreateDir,InstallDir,{FromVsn,_,AllAppsVsns,Path}) ->
{path,Path}]]),
%% Unpack the tar to complete the installation
- erl_tar:extract(RelName ++ ".tar.gz", [{cwd, InstallDir}, compressed]),
+ ok = erl_tar:extract(RelName ++ ".tar.gz", [{cwd, InstallDir}, compressed]),
%% Add bin and log dirs
BinDir = filename:join([InstallDir, "bin"]),
@@ -554,11 +554,11 @@ target_system(Apps,CreateDir,InstallDir,{FromVsn,_,AllAppsVsns,Path}) ->
%% create start_erl.data, sys.config and start.src
StartErlData = filename:join([InstallDir, "releases", "start_erl.data"]),
- write_file(StartErlData, io_lib:fwrite("~s ~s~n", [ErtsVsn, FromVsn])),
+ ok = write_file(StartErlData, io_lib:fwrite("~s ~s~n", [ErtsVsn, FromVsn])),
SysConfig = filename:join([InstallDir, "releases", FromVsn, "sys.config"]),
- write_file(SysConfig, "[]."),
+ ok = write_file(SysConfig, "[]."),
StartSrc = filename:join(ErtsBinDir,"start.src"),
- write_file(StartSrc,start_script()),
+ ok = write_file(StartSrc,start_script()),
ok = file:change_mode(StartSrc,8#0755),
%% Make start_erl executable
@@ -620,7 +620,7 @@ upgrade_system(Apps, FromRel, CreateDir, InstallDir, {_,ToVsn,_,_}) ->
[{path,[FromPath]},
{outdir,CreateDir}]]),
SysConfig = filename:join([CreateDir, "sys.config"]),
- write_file(SysConfig, "[]."),
+ ok = write_file(SysConfig, "[]."),
ok = systools(make_tar,[RelName,[{erts,code:root_dir()}]]),
@@ -858,7 +858,7 @@ subst_file(Src, Dest, Vars, Opts) ->
{ok, Bin} = file:read_file(Src),
Conts = unicode:characters_to_list(Bin),
NConts = subst(Conts, Vars),
- write_file(Dest, NConts),
+ ok = write_file(Dest, NConts),
case lists:member(preserve, Opts) of
true ->
{ok, FileInfo} = file:read_file_info(Src),
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index f9abecfd38..58a29edace 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -1085,7 +1085,7 @@ match_line(Name,Pid,Line,[Pattern|Patterns],FoundPrompt,Term,EO,RetTag) ->
end;
match_line(Name,Pid,Line,[],FoundPrompt,Term,EO,match) ->
match_line(Name,Pid,Line,EO#eo.haltpatterns,FoundPrompt,Term,EO,halt);
-%% print any terminated line that can not be matched
+%% print any terminated line that cannot be matched
match_line(Name,Pid,Line,[],_FoundPrompt,true,_EO,halt) ->
log(name_or_pid(Name,Pid)," ~ts",[Line]),
nomatch;
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index d8fd401a64..9f489e9bfb 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -192,7 +192,10 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
ok
end,
- ct_default_gl:start_link(group_leader()),
+ case ct_default_gl:start_link(group_leader()) of
+ {ok, _} -> ok;
+ ignore -> ok
+ end,
{StartTime,TestLogDir} = ct_logs:init(Mode, Verbosity),
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
index 99c484de48..86081369b9 100644
--- a/lib/common_test/src/cth_log_redirect.erl
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -124,7 +124,8 @@ start_log_handler() ->
shutdown=>2000,
type=>worker,
modules=>[?MODULE]},
- {ok,_} = supervisor:start_child(logger_sup,ChildSpec);
+ {ok,_} = supervisor:start_child(logger_sup,ChildSpec),
+ ok;
_Pid ->
ok
end,
@@ -184,21 +185,12 @@ handle_call({log,#{meta:=#{gl:=GL}},_}, _From,
{reply, ok, State};
handle_call({log,
- #{msg:=Msg0,
- meta:=#{?MODULE:=#{category:=Category}}=Meta}=Log,
+ #{meta:=#{?MODULE:=#{category:=Category}}}=Log,
#{formatter:={Formatter,FConfig}}},
_From,
#eh_state{log_func=LogFunc}=State) ->
Header = format_header(State),
- Msg =
- case Msg0 of
- {report,R} ->
- Fun=maps:get(report_cb,Meta,fun logger:format_report/1),
- Fun(R);
- _ ->
- Msg0
- end,
- String = Formatter:format(Log#{msg=>Msg},FConfig),
+ String = Formatter:format(Log,FConfig),
case LogFunc of
tc_log ->
ct_logs:tc_log(Category, ?STD_IMPORTANCE,
diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl
index 8bd6cd583a..34f2feb33c 100644
--- a/lib/common_test/src/test_server_ctrl.erl
+++ b/lib/common_test/src/test_server_ctrl.erl
@@ -1393,7 +1393,7 @@ temp_nodename([Chr|Base], Acc) ->
%%
%% Counts the test cases that are about to run and returns that number.
%% If there's a conf group in TestSpec with a repeat property, the total number
-%% of cases can not be calculated and NoOfCases = unknown.
+%% of cases cannot be calculated and NoOfCases = unknown.
count_test_cases(TopCases, SkipCases) when is_list(TopCases) ->
case collect_all_cases(TopCases, SkipCases) of
{error,_Why} = Error ->
@@ -4906,7 +4906,7 @@ collect_files(Dir, Pattern, St, Mode) ->
fullname_to_mod(Path) when is_list(Path) ->
%% If this is called with a binary, then we are probably in +fnu
%% mode and have found a beam file with name encoded as latin1. We
- %% will let this crash since it can not work to load such a module
+ %% will let this crash since it cannot work to load such a module
%% anyway. It should be removed or renamed!
list_to_atom(filename:rootname(filename:basename(Path))).
diff --git a/lib/common_test/test/ct_auto_compile_SUITE.erl b/lib/common_test/test/ct_auto_compile_SUITE.erl
index dface99b8f..f88f13c889 100644
--- a/lib/common_test/test/ct_auto_compile_SUITE.erl
+++ b/lib/common_test/test/ct_auto_compile_SUITE.erl
@@ -169,7 +169,7 @@ test_events(ac_flag) ->
{?eh,start_info,{1,1,3}},
{?eh,tc_start,{ct_framework,error_in_suite}},
{?eh,tc_done,{ct_framework,error_in_suite,
- {failed,{error,'bad_SUITE can not be compiled or loaded'}}}},
+ {failed,{error,'bad_SUITE cannot be compiled or loaded'}}}},
{?eh,tc_start,{dummy_SUITE,init_per_suite}},
{?eh,tc_done,{dummy_SUITE,init_per_suite,ok}},
{?eh,test_stats,{1,1,{1,0}}},
@@ -186,7 +186,7 @@ test_events(ac_spec) ->
{?eh,start_info,{1,1,3}},
{?eh,tc_start,{ct_framework,error_in_suite}},
{?eh,tc_done,{ct_framework,error_in_suite,
- {failed,{error,'bad_SUITE can not be compiled or loaded'}}}},
+ {failed,{error,'bad_SUITE cannot be compiled or loaded'}}}},
{?eh,tc_start,{dummy_SUITE,init_per_suite}},
{?eh,tc_done,{dummy_SUITE,init_per_suite,ok}},
{?eh,test_stats,{1,1,{1,0}}},
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index a2fa099a8c..0a374d7404 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -205,7 +205,7 @@ hello_required_exists(Config) ->
SshDir = ?config(ssh_dir,Config),
{ok,_Client1} = open_configured_success(my_named_connection,SshDir),
- %% Check that same name can not be used twice
+ %% Check that same name cannot be used twice
{error,{connection_exists,_Client1}} =
ct_netconfc:open(my_named_connection,[{user_dir,SshDir}]),
@@ -385,7 +385,7 @@ timeout_get(Config) ->
%% received, the timeout message might already be sent when the timer
%% is cancelled. This test checks that the timeout message is flushed
%% from the message queue. If it isn't, the client crashes and the
-%% session can not be closed afterwards.
+%% session cannot be closed afterwards.
%% Note that we can only hope that the test case triggers the problem
%% every now and then, as it is very timing dependent...
flush_timeout_get(Config) ->
diff --git a/lib/common_test/test/test_server_SUITE.erl b/lib/common_test/test/test_server_SUITE.erl
index 05737cfac9..6e52f24025 100644
--- a/lib/common_test/test/test_server_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE.erl
@@ -260,7 +260,7 @@ translate_filename(Filename,EncodingOnTestNode) ->
end.
get_latest_run_dir(Dir) ->
- %% For the time being, filelib:wildcard can not take a binary
+ %% For the time being, filelib:wildcard cannot take a binary
%% argument, so we avoid using this here.
case file:list_dir(Dir) of
{ok,Files} ->
@@ -315,7 +315,7 @@ generate_and_run_unicode_test(Config0,Encoding) ->
DataDir = ?config(data_dir,Config0),
Suite = create_unicode_test_suite(DataDir,Encoding),
- %% We can not run this test on default node since it must be
+ %% We cannot run this test on default node since it must be
%% started with correct file name mode (+fnu/+fnl).
%% OBS: the node are stopped by end_per_testcase/2
Config1 = lists:keydelete(node,1,Config0),
diff --git a/lib/common_test/test/test_server_test_lib.erl b/lib/common_test/test/test_server_test_lib.erl
index 9ee946af0b..58b3aaee9b 100644
--- a/lib/common_test/test/test_server_test_lib.erl
+++ b/lib/common_test/test/test_server_test_lib.erl
@@ -22,7 +22,7 @@
-export([parse_suite/1]).
-export([init/2, pre_init_per_testcase/3, post_end_per_testcase/4]).
-%% for test_server_SUITE when node can not be started as slave
+%% for test_server_SUITE when node cannot be started as slave
-export([prepare_tester_node/2]).
-include("test_server_test_lib.hrl").
diff --git a/lib/compiler/doc/src/Makefile b/lib/compiler/doc/src/Makefile
index 13210de040..661415899f 100644
--- a/lib/compiler/doc/src/Makefile
+++ b/lib/compiler/doc/src/Makefile
@@ -89,6 +89,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 997a506181..671126b73b 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,68 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an issue where files compiled with the
+ <c>+deterministic</c> option differed if they were
+ compiled in a different directory but were otherwise
+ identical.</p>
+ <p>
+ Own Id: OTP-15204 Aux Id: ERL-679 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>In rare cases involving matching of binary literal
+ strings, the compiler could optimize away code that
+ should be executed.</p>
+ <p>
+ Own Id: OTP-15156 Aux Id: ERL-655 </p>
+ </item>
+ <item>
+ <p>There could be an internal consistency check failure
+ when compiling code that called <c>map_get(Key, Map)</c>
+ and then updated the same map.</p>
+ <p>
+ Own Id: OTP-15157</p>
+ </item>
+ <item>
+ <p>In rare circumstances, the compiler could crash in
+ <c>beam_jump</c> when compiling a floating point
+ operation.</p>
+ <p>
+ Own Id: OTP-15166 Aux Id: ERL-660 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The could could crash when compiling a complicated
+ function that used the binary syntax.</p>
+ <p>
+ Own Id: OTP-15150 Aux Id: ERL-650 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -252,6 +314,23 @@
</section>
+<section><title>Compiler 7.1.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an issue where files compiled with the
+ <c>+deterministic</c> option differed if they were
+ compiled in a different directory but were otherwise
+ identical.</p>
+ <p>
+ Own Id: OTP-15204 Aux Id: ERL-679 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 1c8e0e9854..abc6e96c85 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -310,7 +310,18 @@ btb_reaches_match_2([{test,bs_start_match2,{f,F},Live,[Bin,_],Ctx}|Is],
end;
btb_reaches_match_2([{test,_,{f,F},Ss}=I|Is], Regs, D0) ->
btb_ensure_not_used(Ss, I, Regs),
- D = btb_follow_branch(F, Regs, D0),
+ D1 = btb_follow_branch(F, Regs, D0),
+ D = case Is of
+ [{bs_context_to_binary,_}|_] ->
+ %% bs_context_to_binary following a test instruction
+ %% probably needs the current position to be saved as
+ %% the new start position, but we can't be sure.
+ %% Therefore, conservatively disable the optimization
+ %% (instead of forcing a saving of the position).
+ D1#btb{must_save=true,must_not_save=true};
+ _ ->
+ D1
+ end,
btb_reaches_match_1(Is, Regs, D);
btb_reaches_match_2([{test,_,{f,F},_,Ss,_}=I|Is], Regs, D0) ->
btb_ensure_not_used(Ss, I, Regs),
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 9eee56d604..43084ad588 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -156,41 +156,51 @@ function({function,Name,Arity,CLabel,Asm0}) ->
%%%
share(Is0) ->
- %% We will get more sharing if we never fall through to a label.
- Is = eliminate_fallthroughs(Is0, []),
- share_1(Is, #{}, [], []).
+ Is1 = eliminate_fallthroughs(Is0, []),
+ Is2 = find_fixpoint(fun(Is) ->
+ share_1(Is, #{}, #{}, [], [])
+ end, Is1),
+ reverse(Is2).
-share_1([{label,L}=Lbl|Is], Dict0, [_|_]=Seq, Acc) ->
+share_1([{label,L}=Lbl|Is], Dict0, Lbls0, [_|_]=Seq, Acc) ->
case maps:find(Seq, Dict0) of
- error ->
- Dict = maps:put(Seq, L, Dict0),
- share_1(Is, Dict, [], [Lbl|Seq ++ Acc]);
- {ok,Label} ->
- share_1(Is, Dict0, [], [Lbl,{jump,{f,Label}}|Acc])
+ error ->
+ Dict = maps:put(Seq, L, Dict0),
+ share_1(Is, Dict, Lbls0, [], [[Lbl|Seq]|Acc]);
+ {ok,Label} ->
+ Lbls = maps:put(L, Label, Lbls0),
+ share_1(Is, Dict0, Lbls, [], [[Lbl,{jump,{f,Label}}]|Acc])
end;
-share_1([{func_info,_,_,_}=I|Is], _, [], Acc) ->
- reverse(Is, [I|Acc]);
-share_1([{'catch',_,_}=I|Is], Dict0, Seq, Acc) ->
- Dict = clean_non_sharable(Dict0),
- share_1(Is, Dict, [I|Seq], Acc);
-share_1([{'try',_,_}=I|Is], Dict0, Seq, Acc) ->
- Dict = clean_non_sharable(Dict0),
- share_1(Is, Dict, [I|Seq], Acc);
-share_1([{try_case,_}=I|Is], Dict0, Seq, Acc) ->
- Dict = clean_non_sharable(Dict0),
- share_1(Is, Dict, [I|Seq], Acc);
-share_1([{catch_end,_}=I|Is], Dict0, Seq, Acc) ->
- Dict = clean_non_sharable(Dict0),
- share_1(Is, Dict, [I|Seq], Acc);
-share_1([I|Is], Dict, Seq, Acc) ->
+share_1([{func_info,_,_,_}|_]=Is0, _, Lbls, [], Acc0) when Lbls =/= #{} ->
+ lists:foldl(fun(Is, Acc) ->
+ beam_utils:replace_labels(Is, Acc, Lbls, fun(Old) -> Old end)
+ end, Is0, Acc0);
+share_1([{func_info,_,_,_}|_]=Is, _, Lbls, [], Acc) when Lbls =:= #{} ->
+ lists:foldl(fun lists:reverse/2, Is, Acc);
+share_1([{'catch',_,_}=I|Is], Dict0, Lbls0, Seq, Acc) ->
+ {Dict,Lbls} = clean_non_sharable(Dict0, Lbls0),
+ share_1(Is, Dict, Lbls, [I|Seq], Acc);
+share_1([{'try',_,_}=I|Is], Dict0, Lbls0, Seq, Acc) ->
+ {Dict,Lbls} = clean_non_sharable(Dict0, Lbls0),
+ share_1(Is, Dict, Lbls, [I|Seq], Acc);
+share_1([{try_case,_}=I|Is], Dict0, Lbls0, Seq, Acc) ->
+ {Dict,Lbls} = clean_non_sharable(Dict0, Lbls0),
+ share_1(Is, Dict, Lbls, [I|Seq], Acc);
+share_1([{catch_end,_}=I|Is], Dict0, Lbls0, Seq, Acc) ->
+ {Dict,Lbls} = clean_non_sharable(Dict0, Lbls0),
+ share_1(Is, Dict, Lbls, [I|Seq], Acc);
+share_1([{jump,{f,To}}=I,{label,L}=Lbl|Is], Dict0, Lbls0, _Seq, Acc) ->
+ Lbls = maps:put(L, To, Lbls0),
+ share_1(Is, Dict0, Lbls, [], [[Lbl,I]|Acc]);
+share_1([I|Is], Dict, Lbls, Seq, Acc) ->
case is_unreachable_after(I) of
false ->
- share_1(Is, Dict, [I|Seq], Acc);
+ share_1(Is, Dict, Lbls, [I|Seq], Acc);
true ->
- share_1(Is, Dict, [I], Acc)
+ share_1(Is, Dict, Lbls, [I], Acc)
end.
-clean_non_sharable(Dict) ->
+clean_non_sharable(Dict0, Lbls0) ->
%% We are passing in or out of a 'catch' or 'try' block. Remove
%% sequences that should not be shared over the boundaries of the
%% block. Since the end of the sequence must match, the only
@@ -198,7 +208,17 @@ clean_non_sharable(Dict) ->
%% the 'catch'/'try' block is a sequence that ends with an
%% instruction that causes an exception. Any sequence that causes
%% an exception must contain a line/1 instruction.
- maps:filter(fun(K, _V) -> sharable_with_try(K) end, Dict).
+ Dict1 = maps:to_list(Dict0),
+ Lbls1 = maps:to_list(Lbls0),
+ {Dict2,Lbls2} = foldl(fun({K, V}, {Dict,Lbls}) ->
+ case sharable_with_try(K) of
+ true ->
+ {[{K,V}|Dict],lists:keydelete(V, 2, Lbls)};
+ false ->
+ {Dict,Lbls}
+ end
+ end, {[],Lbls1}, Dict1),
+ {maps:from_list(Dict2),maps:from_list(Lbls2)}.
sharable_with_try([{line,_}|_]) ->
%% This sequence may cause an exception and may potentially
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index b8c3ca1325..b5c979e529 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -559,7 +559,7 @@ update({bs_save2,_,_}, Ts) ->
update({bs_restore2,_,_}, Ts) ->
Ts;
update({bs_context_to_binary,Dst}, Ts) ->
- tdb_store(Dst, {binary,1}, Ts);
+ tdb_store(Dst, any, Ts);
update({test,bs_start_match2,_,_,[Src,_],Dst}, Ts0) ->
Ts = tdb_meet(Src, {binary,1}, Ts0),
tdb_copy(Src, Dst, Ts);
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 5510624b2d..5580d2f123 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -355,6 +355,9 @@ split_even(Rs) -> split_even(Rs, [], []).
%% exit BIF will raise an exception
%% used - Reg is used
+check_liveness({fr,_}, _, St) ->
+ %% Conservatively always consider the floating point register used.
+ {used,St};
check_liveness(R, [{block,Blk}|Is], St0) ->
case check_liveness_block(R, Blk, St0) of
{transparent,St1} ->
@@ -1105,8 +1108,12 @@ defs([{bif,_,{f,Fail},_Src,Dst}=I|Is], Regs0, D) ->
defs([{block,Block0}|Is], Regs0, D0) ->
{Block,Regs,D} = defs_list(Block0, Regs0, D0),
[{block,[make_anno({def,Regs0})|Block]}|defs(Is, Regs, D)];
-defs([{bs_init,{f,L},_,_,_,Dst}=I|Is], Regs0, D) ->
- Regs = def_regs([Dst], Regs0),
+defs([{bs_init,{f,L},_,Live,_,Dst}=I|Is], Regs0, D) ->
+ Regs1 = case Live of
+ none -> Regs0;
+ _ -> init_def_regs(Live)
+ end,
+ Regs = def_regs([Dst], Regs1),
[I|defs(Is, Regs, update_regs(L, Regs, D))];
defs([{bs_put,{f,L},_,_}=I|Is], Regs, D) ->
[I|defs(Is, Regs, update_regs(L, Regs, D))];
@@ -1157,7 +1164,7 @@ defs([{loop_rec,{f,L},{x,0}}=I|Is], _Regs, D0) ->
D = update_regs(L, RegsAtLabel, D0),
[I|defs(Is, init_def_regs(1), D)];
defs([{loop_rec_end,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 0, D)];
+ [I|defs_unreachable(Is, D)];
defs([{make_fun2,_,_,_,_}=I|Is], _Regs, D) ->
[I|defs(Is, 1, D)];
defs([{move,_,Dst}=I|Is], Regs0, D) ->
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index b03fadb197..c09dbadd7f 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -280,7 +280,7 @@ valfun_1({try_case_end,Src}, Vst) ->
verify_y_init(Vst),
assert_term(Src, Vst),
kill_state(Vst);
-%% Instructions that can not cause exceptions
+%% Instructions that cannot cause exceptions
valfun_1({bs_context_to_binary,Ctx}, #vst{current=#st{x=Xs}}=Vst) ->
case Ctx of
{Tag,X} when Tag =:= x; Tag =:= y ->
@@ -451,6 +451,19 @@ valfun_1({try_case,Reg}, #vst{current=#st{ct=[Fail|Fails]}}=Vst0) ->
Type ->
error({bad_type,Type})
end;
+valfun_1({get_list,Src,D1,D2}, Vst0) ->
+ assert_type(cons, Src, Vst0),
+ Vst = set_type_reg(term, Src, D1, Vst0),
+ set_type_reg(term, Src, D2, Vst);
+valfun_1({get_hd,Src,Dst}, Vst) ->
+ assert_type(cons, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
+valfun_1({get_tl,Src,Dst}, Vst) ->
+ assert_type(cons, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
+valfun_1({get_tuple_element,Src,I,Dst}, Vst) ->
+ assert_type({tuple_element,I+1}, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
valfun_1(I, Vst) ->
valfun_2(I, Vst).
@@ -546,6 +559,12 @@ valfun_4({bif,raise,{f,0},Src,_Dst}, Vst) ->
kill_state(Vst);
valfun_4(raw_raise=I, Vst) ->
call(I, 3, Vst);
+valfun_4({bif,map_get,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(term, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
validate_src(Src, Vst0),
Vst = branch_state(Fail, Vst0),
@@ -603,19 +622,6 @@ valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
valfun_4({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
assert_type(tuple, Tuple, Vst),
kill_state(branch_arities(Choices, Tuple, branch_state(Fail, Vst)));
-valfun_4({get_list,Src,D1,D2}, Vst0) ->
- assert_type(cons, Src, Vst0),
- Vst = set_type_reg(term, Src, D1, Vst0),
- set_type_reg(term, Src, D2, Vst);
-valfun_4({get_hd,Src,Dst}, Vst) ->
- assert_type(cons, Src, Vst),
- set_type_reg(term, Src, Dst, Vst);
-valfun_4({get_tl,Src,Dst}, Vst) ->
- assert_type(cons, Src, Vst),
- set_type_reg(term, Src, Dst, Vst);
-valfun_4({get_tuple_element,Src,I,Dst}, Vst) ->
- assert_type({tuple_element,I+1}, Src, Vst),
- set_type_reg(term, Src, Dst, Vst);
%% New bit syntax matching instructions.
valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 5ef9611504..e1c1f7338e 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1432,16 +1432,30 @@ encrypt_debug_info(DebugInfo, Key, Opts) ->
end.
cleanup_compile_options(Opts) ->
- lists:filter(fun keep_compile_option/1, Opts).
-
+ IsDeterministic = lists:member(deterministic, Opts),
+ lists:filter(fun(Opt) ->
+ keep_compile_option(Opt, IsDeterministic)
+ end, Opts).
+
+%% Include paths and current directory don't affect compilation, but they might
+%% be helpful so we include them unless we're doing a deterministic build.
+keep_compile_option({i, _}, Deterministic) ->
+ not Deterministic;
+keep_compile_option({cwd, _}, Deterministic) ->
+ not Deterministic;
%% We are storing abstract, not asm or core.
-keep_compile_option(from_asm) -> false;
-keep_compile_option(from_core) -> false;
+keep_compile_option(from_asm, _Deterministic) ->
+ false;
+keep_compile_option(from_core, _Deterministic) ->
+ false;
%% Parse transform and macros have already been applied.
-keep_compile_option({parse_transform, _}) -> false;
-keep_compile_option({d, _, _}) -> false;
+keep_compile_option({parse_transform, _}, _Deterministic) ->
+ false;
+keep_compile_option({d, _, _}, _Deterministic) ->
+ false;
%% Do not affect compilation result on future calls.
-keep_compile_option(Option) -> effects_code_generation(Option).
+keep_compile_option(Option, _Deterministic) ->
+ effects_code_generation(Option).
start_crypto() ->
try crypto:start() of
@@ -1589,6 +1603,7 @@ effects_code_generation(Option) ->
binary -> false;
verbose -> false;
{cwd,_} -> false;
+ {i,_} -> false;
{outdir, _} -> false;
_ -> true
end.
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index 68489a0122..71ab0e872a 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -91,6 +91,7 @@ is_pure(erlang, is_bitstring, 1) -> true;
%% erlang:is_builtin/3 depends on the state (i.e. the version of the emulator).
is_pure(erlang, is_float, 1) -> true;
is_pure(erlang, is_function, 1) -> true;
+is_pure(erlang, is_function, 2) -> true;
is_pure(erlang, is_integer, 1) -> true;
is_pure(erlang, is_list, 1) -> true;
is_pure(erlang, is_map, 1) -> true;
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index 02dead9e92..f35ae09fe7 100755
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -142,8 +142,7 @@ BEAM_FORMAT_NUMBER=0
20: send/0
## @spec remove_message
-## @doc Unlink the current message from the message queue and store a
-## pointer to the message in x(0). Remove any timeout.
+## @doc Unlink the current message from the message queue. Remove any timeout.
21: remove_message/0
## @spec timeout
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index ceb7d56221..d848cd8f19 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -99,7 +99,7 @@
t=#{} :: map(), %Types
in_guard=false}). %In guard or not.
--type type_info() :: cerl:cerl() | 'bool' | 'integer'.
+-type type_info() :: cerl:cerl() | 'bool' | 'integer' | {'fun', pos_integer()}.
-type yes_no_maybe() :: 'yes' | 'no' | 'maybe'.
-type sub() :: #sub{}.
@@ -115,13 +115,6 @@ module(#c_module{defs=Ds0}=Mod, Opts) ->
{ok,Mod#c_module{defs=Ds1},get_warnings()}.
function_1({#c_var{name={F,Arity}}=Name,B0}) ->
- %% Find a suitable starting value for the variable counter. Note
- %% that this pass assumes that new_var_name/1 returns a variable
- %% name distinct from any variable used in the entire body of
- %% the function. We use integers as variable names to avoid
- %% filling up the atom table when compiling huge functions.
- Count = cerl_trees:next_free_variable_name(B0),
- put(new_var_num, Count),
try
%% Find a suitable starting value for the variable
%% counter. Note that this pass assumes that new_var_name/1
@@ -352,7 +345,12 @@ expr(#c_letrec{body=#c_var{}}=Letrec, effect, _Sub) ->
void();
expr(#c_letrec{defs=Fs0,body=B0}=Letrec, Ctxt, Sub) ->
Fs1 = map(fun ({Name,Fb}) ->
- {Name,expr(Fb, {letrec,Ctxt}, Sub)}
+ case Ctxt =:= effect andalso is_fun_effect_safe(Name, B0) of
+ true ->
+ {Name,expr(Fb, {letrec, effect}, Sub)};
+ false ->
+ {Name,expr(Fb, {letrec, value}, Sub)}
+ end
end, Fs0),
B1 = body(B0, Ctxt, Sub),
Letrec#c_letrec{defs=Fs1,body=B1};
@@ -480,9 +478,101 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0)
false ->
{Evs1,Sub2} = var_list(Evs0, Sub0),
H1 = body(H0, value, Sub2),
- Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}
+ H2 = opt_try_handler(H1, lists:last(Evs1)),
+ Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H2}
end.
+%% Attempts to convert old erlang:get_stacktrace/0 calls into the new
+%% three-argument catch, with possibility of further optimisations.
+opt_try_handler(#c_call{anno=A,module=#c_literal{val=erlang},name=#c_literal{val=get_stacktrace},args=[]}, Var) ->
+ #c_primop{anno=A,name=#c_literal{val=build_stacktrace},args=[Var]};
+opt_try_handler(#c_case{clauses=Cs0} = Case, Var) ->
+ Cs = [C#c_clause{body=opt_try_handler(B, Var)} || #c_clause{body=B} = C <- Cs0],
+ Case#c_case{clauses=Cs};
+opt_try_handler(#c_let{arg=Arg} = Let, Var) ->
+ Let#c_let{arg=opt_try_handler(Arg, Var)};
+opt_try_handler(X, _) -> X.
+
+%% If a fun or its application is used as an argument, then it's unsafe to
+%% handle it in effect context as the side-effects may rely on its return
+%% value. The following is a minimal example of where it can go wrong:
+%%
+%% do letrec 'f'/0 = fun () -> ... whatever ...
+%% in call 'side':'effect'(apply 'f'/0())
+%% 'ok'
+%%
+%% This function returns 'true' if Body definitely does not rely on a
+%% value produced by FVar, or 'false' if Body depends on or might depend on
+%% a value produced by FVar.
+
+is_fun_effect_safe(#c_var{}=FVar, Body) ->
+ ifes_1(FVar, Body, true).
+
+ifes_1(FVar, #c_alias{pat=Pat}, _Safe) ->
+ ifes_1(FVar, Pat, false);
+ifes_1(FVar, #c_apply{op=Op,args=Args}, Safe) ->
+ %% FVar(...) is safe as long its return value is ignored, but it's never
+ %% okay to pass FVar as an argument.
+ ifes_list(FVar, Args, false) andalso ifes_1(FVar, Op, Safe);
+ifes_1(FVar, #c_binary{segments=Segments}, _Safe) ->
+ ifes_list(FVar, Segments, false);
+ifes_1(FVar, #c_bitstr{val=Val,size=Size,unit=Unit}, _Safe) ->
+ ifes_list(FVar, [Val, Size, Unit], false);
+ifes_1(FVar, #c_call{args=Args}, _Safe) ->
+ ifes_list(FVar, Args, false);
+ifes_1(FVar, #c_case{arg=Arg,clauses=Clauses}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_list(FVar, Clauses, Safe);
+ifes_1(FVar, #c_catch{body=Body}, _Safe) ->
+ ifes_1(FVar, Body, false);
+ifes_1(FVar, #c_clause{pats=Pats,guard=Guard,body=Body}, Safe) ->
+ ifes_list(FVar, Pats, false) andalso
+ ifes_1(FVar, Guard, false) andalso
+ ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_cons{hd=Hd,tl=Tl}, _Safe) ->
+ ifes_1(FVar, Hd, false) andalso ifes_1(FVar, Tl, false);
+ifes_1(FVar, #c_fun{body=Body}, _Safe) ->
+ ifes_1(FVar, Body, false);
+ifes_1(FVar, #c_let{arg=Arg,body=Body}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_letrec{defs=Defs,body=Body}, Safe) ->
+ Funs = [Fun || {_,Fun} <- Defs],
+ ifes_list(FVar, Funs, false) andalso ifes_1(FVar, Body, Safe);
+ifes_1(_FVar, #c_literal{}, _Safe) ->
+ true;
+ifes_1(FVar, #c_map{arg=Arg,es=Elements}, _Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_list(FVar, Elements, false);
+ifes_1(FVar, #c_map_pair{key=Key,val=Val}, _Safe) ->
+ ifes_1(FVar, Key, false) andalso ifes_1(FVar, Val, false);
+ifes_1(FVar, #c_primop{args=Args}, _Safe) ->
+ ifes_list(FVar, Args, false);
+ifes_1(FVar, #c_receive{timeout=Timeout,action=Action,clauses=Clauses}, Safe) ->
+ ifes_1(FVar, Timeout, false) andalso
+ ifes_1(FVar, Action, Safe) andalso
+ ifes_list(FVar, Clauses, Safe);
+ifes_1(FVar, #c_seq{arg=Arg,body=Body}, Safe) ->
+ %% Arg of a #c_seq{} has no effect so it's okay to use FVar there even if
+ %% Safe=false.
+ ifes_1(FVar, Arg, true) andalso ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_try{arg=Arg,handler=Handler,body=Body}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso
+ ifes_1(FVar, Handler, Safe) andalso
+ ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_tuple{es=Elements}, _Safe) ->
+ ifes_list(FVar, Elements, false);
+ifes_1(FVar, #c_values{es=Elements}, _Safe) ->
+ ifes_list(FVar, Elements, false);
+ifes_1(#c_var{name=Name}, #c_var{name=Name}, Safe) ->
+ %% It's safe to return FVar if it's unused.
+ Safe;
+ifes_1(_FVar, #c_var{}, _Safe) ->
+ true.
+
+ifes_list(FVar, [E|Es], Safe) ->
+ ifes_1(FVar, E, Safe) andalso ifes_list(FVar, Es, Safe);
+ifes_list(_FVar, [], _Safe) ->
+ true.
+
+
expr_list(Es, Ctxt, Sub) ->
[expr(E, Ctxt, Sub) || E <- Es].
@@ -883,6 +973,10 @@ fold_non_lit_args(Call, erlang, setelement, [Arg1,Arg2,Arg3], _) ->
eval_setelement(Call, Arg1, Arg2, Arg3);
fold_non_lit_args(Call, erlang, is_record, [Arg1,Arg2,Arg3], Sub) ->
eval_is_record(Call, Arg1, Arg2, Arg3, Sub);
+fold_non_lit_args(Call, erlang, is_function, [Arg1], Sub) ->
+ eval_is_function_1(Call, Arg1, Sub);
+fold_non_lit_args(Call, erlang, is_function, [Arg1,Arg2], Sub) ->
+ eval_is_function_2(Call, Arg1, Arg2, Sub);
fold_non_lit_args(Call, erlang, N, Args, Sub) ->
NumArgs = length(Args),
case erl_internal:comp_op(N, NumArgs) of
@@ -898,6 +992,22 @@ fold_non_lit_args(Call, erlang, N, Args, Sub) ->
end;
fold_non_lit_args(Call, _, _, _, _) -> Call.
+eval_is_function_1(Call, Arg1, Sub) ->
+ case get_type(Arg1, Sub) of
+ none -> Call;
+ {'fun',_} -> #c_literal{anno=cerl:get_ann(Call),val=true};
+ _ -> #c_literal{anno=cerl:get_ann(Call),val=false}
+ end.
+
+eval_is_function_2(Call, Arg1, #c_literal{val=Arity}, Sub)
+ when is_integer(Arity), Arity > 0 ->
+ case get_type(Arg1, Sub) of
+ none -> Call;
+ {'fun',Arity} -> #c_literal{anno=cerl:get_ann(Call),val=true};
+ _ -> #c_literal{anno=cerl:get_ann(Call),val=false}
+ end;
+eval_is_function_2(Call, _Arg1, _Arg2, _Sub) -> Call.
+
%% Evaluate a relational operation using type information.
eval_rel_op(Call, Op, [#c_var{name=V},#c_var{name=V}], _) ->
Bool = erlang:Op(same, same),
@@ -3105,6 +3215,10 @@ update_types_2(V, [#c_tuple{}=P], Types) ->
Types#{V=>P};
update_types_2(V, [#c_literal{val=Bool}], Types) when is_boolean(Bool) ->
Types#{V=>bool};
+update_types_2(V, [#c_fun{vars=Vars}], Types) ->
+ Types#{V=>{'fun',length(Vars)}};
+update_types_2(V, [#c_var{name={_,Arity}}], Types) ->
+ Types#{V=>{'fun',Arity}};
update_types_2(V, [Type], Types) when is_atom(Type) ->
Types#{V=>Type};
update_types_2(_, _, Types) -> Types.
@@ -3123,6 +3237,8 @@ kill_types2(V, [{_,#c_tuple{}=Tuple}=Entry|Tdb]) ->
false -> [Entry|kill_types2(V, Tdb)];
true -> kill_types2(V, Tdb)
end;
+kill_types2(V, [{_, {'fun',_}}=Entry|Tdb]) ->
+ [Entry|kill_types2(V, Tdb)];
kill_types2(V, [{_,Atom}=Entry|Tdb]) when is_atom(Atom) ->
[Entry|kill_types2(V, Tdb)];
kill_types2(_, []) -> [].
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 6cd114abf7..e9152ba88f 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1621,11 +1621,6 @@ test_cg(is_boolean, [#k_atom{val=Val}], Fail, I, Vdb, Bef, St) ->
false -> [{jump,{f,Fail}}]
end,
{Is,Aft,St};
-test_cg(is_map_key, As, Fail, I, Vdb, Bef, St) ->
- [Key,Map] = cg_reg_args(As, Bef),
- Aft = clear_dead(Bef, I, Vdb),
- F = {f,Fail},
- {[{test,is_map,F,[Map]},{test,has_map_fields,F,Map,{list,[Key]}}],Aft,St};
test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
Args = cg_reg_args(As, Bef),
Aft = clear_dead(Bef, I, Vdb),
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 0196e7fdfd..3b746ab5bf 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1501,7 +1501,7 @@ bc_initial_size(E0, Q, St0) ->
end.
bc_elem_size({bin,_,El}, St0) ->
- case bc_elem_size_1(El, 0, []) of
+ case bc_elem_size_1(El, ordsets:new(), 0, []) of
{Bits,[]} ->
{#c_literal{val=Bits},[],[],St0};
{Bits,Vars0} ->
@@ -1515,19 +1515,33 @@ bc_elem_size(_, _) ->
throw(impossible).
bc_elem_size_1([{bin_element,_,{string,_,String},{integer,_,N},_}=El|Es],
- Bits, Vars) ->
+ DefVars, Bits, SizeVars) ->
U = get_unit(El),
- bc_elem_size_1(Es, Bits+U*N*length(String), Vars);
-bc_elem_size_1([{bin_element,_,_,{integer,_,N},_}=El|Es], Bits, Vars) ->
+ bc_elem_size_1(Es, DefVars, Bits+U*N*length(String), SizeVars);
+bc_elem_size_1([{bin_element,_,Expr,{integer,_,N},_}=El|Es],
+ DefVars0, Bits, SizeVars) ->
U = get_unit(El),
- bc_elem_size_1(Es, Bits+U*N, Vars);
-bc_elem_size_1([{bin_element,_,_,{var,_,Var},_}=El|Es], Bits, Vars) ->
- U = get_unit(El),
- bc_elem_size_1(Es, Bits, [{U,#c_var{name=Var}}|Vars]);
-bc_elem_size_1([_|_], _, _) ->
+ DefVars = bc_elem_size_def_var(Expr, DefVars0),
+ bc_elem_size_1(Es, DefVars, Bits+U*N, SizeVars);
+bc_elem_size_1([{bin_element,_,Expr,{var,_,Src},_}=El|Es],
+ DefVars0, Bits, SizeVars) ->
+ case ordsets:is_element(Src, DefVars0) of
+ false ->
+ U = get_unit(El),
+ DefVars = bc_elem_size_def_var(Expr, DefVars0),
+ bc_elem_size_1(Es, DefVars, Bits, [{U,#c_var{name=Src}}|SizeVars]);
+ true ->
+ throw(impossible)
+ end;
+bc_elem_size_1([_|_], _, _, _) ->
throw(impossible);
-bc_elem_size_1([], Bits, Vars) ->
- {Bits,Vars}.
+bc_elem_size_1([], _DefVars, Bits, SizeVars) ->
+ {Bits,SizeVars}.
+
+bc_elem_size_def_var({var,_,Var}, DefVars) ->
+ ordsets:add_element(Var, DefVars);
+bc_elem_size_def_var(_Expr, DefVars) ->
+ DefVars.
bc_elem_size_combine([{U,V}|T], U, UVars, Acc) ->
bc_elem_size_combine(T, U, [V|UVars], Acc);
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index 05c087104d..721f77f0f6 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -29,7 +29,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -38,6 +37,7 @@ groups() ->
combined,in_case,slow_compilation]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index cca92e4713..be49cff9b9 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -29,13 +29,13 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[mfa, fun_apply].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_block_SUITE.erl b/lib/compiler/test/beam_block_SUITE.erl
index d40addf119..40a30b65d7 100644
--- a/lib/compiler/test/beam_block_SUITE.erl
+++ b/lib/compiler/test/beam_block_SUITE.erl
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -46,6 +45,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index 47367d6eab..1eb07c8c85 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -26,7 +26,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -35,6 +34,7 @@ groups() ->
coverage]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl
index 088f63606c..488c30919b 100644
--- a/lib/compiler/test/beam_jump_SUITE.erl
+++ b/lib/compiler/test/beam_jump_SUITE.erl
@@ -27,7 +27,6 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -37,6 +36,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl
index 27ce51eec3..33b27b9f9f 100644
--- a/lib/compiler/test/beam_reorder_SUITE.erl
+++ b/lib/compiler/test/beam_reorder_SUITE.erl
@@ -26,7 +26,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -36,6 +35,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 499b9b41df..061076b3ff 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -23,12 +23,11 @@
init_per_group/2,end_per_group/2,
integers/1,coverage/1,booleans/1,setelement/1,cons/1,
tuple/1,record_float/1,binary_float/1,float_compare/1,
- arity_checks/1,elixir_binaries/1]).
+ arity_checks/1,elixir_binaries/1,find_best/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -43,10 +42,12 @@ groups() ->
binary_float,
float_compare,
arity_checks,
- elixir_binaries
+ elixir_binaries,
+ find_best
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -292,6 +293,33 @@ elixir_bitstring_3(Bar) when is_bitstring(Bar) ->
list_to_bitstring(Rewrite)
end/bitstring>>.
+find_best(_Config) ->
+ ok = find_best([a], nil),
+ ok = find_best([<<"a">>], nil),
+ {error,_} = find_best([], nil),
+ ok.
+
+%% Failed because beam_type assumed that the operand
+%% for bs_context_binary must be a binary. Not true!
+find_best([a|Tail], Best) ->
+ find_best(Tail,
+ case Best of
+ X when X =:= nil orelse X =:= false -> a;
+ X -> X
+ end);
+find_best([<<"a">>|Tail], Best) ->
+ find_best(Tail,
+ case Best of
+ X when X =:= nil orelse X =:= false -> <<"a">>;
+ X -> X
+ end);
+find_best([], a) ->
+ ok;
+find_best([], <<"a">>) ->
+ ok;
+find_best([], nil) ->
+ {error,<<"should not get here">>}.
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl
index 3d35b546fc..ac19305d69 100644
--- a/lib/compiler/test/beam_utils_SUITE.erl
+++ b/lib/compiler/test/beam_utils_SUITE.erl
@@ -25,13 +25,13 @@
is_not_killed/1,is_not_used_at/1,
select/1,y_catch/1,otp_8949_b/1,liveopt/1,coverage/1,
y_registers/1,user_predef/1,scan_f/1,cafu/1,
- receive_label/1,read_size_file_version/1,not_used/1]).
+ receive_label/1,read_size_file_version/1,not_used/1,
+ is_used_fr/1]).
-export([id/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -52,10 +52,12 @@ groups() ->
scan_f,
cafu,
read_size_file_version,
- not_used
+ not_used,
+ is_used_fr
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -132,6 +134,15 @@ bs_init(_Config) ->
<<"foo/foo">> = do_bs_init_4(<<"foo">>, true),
error = do_bs_init_4([], not_boolean),
+ Id = 17575,
+ Domain = -8798798,
+ [<<10,1:16,Id:16/signed>>,<<8,2:16,Domain:32/signed>>] =
+ do_bs_init_5(#{tag=>value,id=>Id,domain=>Domain}),
+ {'EXIT',{{required,id},[_|_]}} =
+ (catch do_bs_init_5(#{tag=>value,id=>nil,domain=>Domain})),
+ {'EXIT',{{required,domain},[_|_]}} =
+ (catch do_bs_init_5(#{tag=>value,id=>Id,domain=>nil})),
+
ok.
do_bs_init_1([?MODULE], Sz) ->
@@ -189,6 +200,20 @@ do_bs_init_4(Arg1, Arg2) ->
error
end.
+do_bs_init_5(#{tag := value, id := Id, domain := Domain}) ->
+ [case Id of
+ nil ->
+ error(id({required, id}));
+ _ ->
+ <<10, 1:16/signed, Id:16/signed>>
+ end,
+ case Domain of
+ nil ->
+ error(id({required, domain}));
+ _ ->
+ <<8, 2:16/signed, Domain:32/signed>>
+ end].
+
bs_save(_Config) ->
{a,30,<<>>} = do_bs_save(<<1:1,30:5>>),
{b,127,<<>>} = do_bs_save(<<1:1,31:5,0:1,127:7>>),
@@ -527,5 +552,24 @@ not_used_p(_C, S, K, L) when is_record(K, k) ->
id(K)
end.
+is_used_fr(Config) ->
+ 1 = is_used_fr(self(), self()),
+ 1 = is_used_fr(self(), other),
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ ok.
+
+is_used_fr(X, Y) ->
+ %% beam_utils:is_used({fr,R}, Code) would crash.
+ _ = 0 / (X ! 1),
+ _ = case Y of
+ X -> ok;
+ _ -> error
+ end,
+ X ! 1.
+
+
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 374f7645d8..d3e544a9cc 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -49,7 +49,6 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -67,6 +66,7 @@ groups() ->
receive_stacked]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index bba2058f2f..c4c709eb3a 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -29,7 +29,6 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,6 +39,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index dd1d245f88..a5d49020a9 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -26,22 +26,22 @@
init_per_group/2,end_per_group/2,
byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1,
- nomatch/1,sizes/1,general_expressions/1]).
+ nomatch/1,sizes/1,general_expressions/1,matched_out_size/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[byte_aligned, bit_aligned, extended_byte_aligned,
extended_bit_aligned, mixed, filters, trim_coverage,
- nomatch, sizes, general_expressions].
+ nomatch, sizes, general_expressions, matched_out_size].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -338,6 +338,13 @@ general_expressions(_) ->
-undef(BAD).
+matched_out_size(Config) when is_list(Config) ->
+ <<1, 2>> = matched_out_size_1(<<4, 1:4, 4, 2:4>>),
+ ok.
+
+matched_out_size_1(Binary) ->
+ << <<X>> || <<S, X:S>> <= Binary>>.
+
cs_init() ->
erts_debug:set_internal_state(available_internal_state, true),
ok.
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index 208d8c5487..17faa012bc 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -34,7 +34,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -43,9 +42,10 @@ groups() ->
asymmetric_tests,big_asymmetric_tests,
binary_to_and_from_list,big_binary_to_and_from_list,
send_and_receive,send_and_receive_alot]}].
-
+
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index aa41baf7f0..ccc49df005 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -38,11 +38,10 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
-all() ->
- test_lib:recompile(?MODULE),
+all() ->
[{group,p}].
-groups() ->
+groups() ->
[{p,[parallel],
[two,test1,fail,float_bin,in_guard,in_catch,
nasty_literals,side_effect,opt,otp_7556,float_arith,
@@ -50,6 +49,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 861fafb867..7814738449 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -40,7 +40,7 @@
map_and_binary/1,unsafe_branch_caching/1,
bad_literals/1,good_literals/1,constant_propagation/1,
parse_xml/1,get_payload/1,escape/1,num_slots_different/1,
- beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1]).
+ beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,erl_689/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -53,7 +53,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -73,10 +72,11 @@ groups() ->
map_and_binary,unsafe_branch_caching,
bad_literals,good_literals,constant_propagation,parse_xml,
get_payload,escape,num_slots_different,
- beam_bsm,guard,is_ascii,non_opt_eq]}].
+ beam_bsm,guard,is_ascii,non_opt_eq,erl_689]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -1688,6 +1688,35 @@ non_opt_eq([_|_], <<_,_/binary>>) ->
non_opt_eq([], <<>>) ->
true.
+%% ERL-689
+
+erl_689(Config) ->
+ {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE),
+ {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE),
+ {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>),
+ {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>),
+ ok.
+
+do_erl_689_1(<<Length, Data/binary>>, _) ->
+ case {Data, Length} of
+ {_, 0} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ {{0, 0, 0}, Data};
+ {<<Y:16/little, M, D, Rest/binary>>, 4} ->
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_2(_, <<Length, Data/binary>>) ->
+ case {Length, Data} of
+ {0, _} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ {{0, 0, 0}, Data};
+ {4, <<Y:16/little, M, D, Rest/binary>>} ->
+ {{Y, M, D}, Rest}
+ end.
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index ef3fc54b37..4330677260 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[utf8_roundtrip, unused_utf_char, utf16_roundtrip,
utf32_roundtrip, guard, extreme_tripping, literals,
coverage].
@@ -40,6 +39,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index a4de125d32..3ba3ce7cdf 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -66,7 +66,6 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- test_lib:recompile(?MODULE),
[self_compile_old_inliner,self_compile,
{group,p}].
@@ -88,6 +87,7 @@ groups() ->
string_table,otp_8949_a,split_cases]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 5373df01d6..1ecae06128 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -36,7 +36,7 @@
core_roundtrip/1, asm/1, optimized_guards/1,
sys_pre_attributes/1, dialyzer/1,
warnings/1, pre_load_check/1, env_compiler_options/1,
- bc_options/1
+ bc_options/1, deterministic_include/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -46,7 +46,6 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> all_return_type().
all() ->
- test_lib:recompile(?MODULE),
[app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, kernel_listing, encrypted_abstr, tuple_calls,
@@ -54,12 +53,13 @@ all() ->
cover, env, core_pp, core_roundtrip, asm, optimized_guards,
sys_pre_attributes, dialyzer, warnings, pre_load_check,
env_compiler_options, custom_debug_info, bc_options,
- custom_compile_info].
+ custom_compile_info, deterministic_include].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -1514,6 +1514,23 @@ highest_opcode(DataDir, Mod, Opt) ->
<<16:32,0:32,HighestOpcode:32,_/binary>> = Code,
HighestOpcode.
+deterministic_include(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ Simple = filename:join(DataDir, "simple"),
+
+ %% Files without +deterministic should differ if their include paths do,
+ %% as their debug info will be different.
+ {ok,_,NonDetA} = compile:file(Simple, [binary, {i,"gurka"}]),
+ {ok,_,NonDetB} = compile:file(Simple, [binary, {i,"gaffel"}]),
+ true = NonDetA =/= NonDetB,
+
+ %% ... but files with +deterministic shouldn't.
+ {ok,_,DetC} = compile:file(Simple, [binary, deterministic, {i,"gurka"}]),
+ {ok,_,DetD} = compile:file(Simple, [binary, deterministic, {i,"gaffel"}]),
+ true = DetC =:= DetD,
+
+ ok.
+
%%%
%%% Utilities.
%%%
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 9d872b860b..e5611e99d1 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -29,7 +29,7 @@
bs_shadowed_size_var/1,
cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1,
cover_v3_kernel_4/1,cover_v3_kernel_5/1,
- non_variable_apply/1,name_capture/1]).
+ non_variable_apply/1,name_capture/1,fun_letrec_effect/1]).
-include_lib("common_test/include/ct.hrl").
@@ -47,7 +47,6 @@ suite() ->
{timetrap,{minutes,5}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -58,11 +57,12 @@ groups() ->
bs_shadowed_size_var,
cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3,
cover_v3_kernel_4,cover_v3_kernel_5,
- non_variable_apply,name_capture
+ non_variable_apply,name_capture,fun_letrec_effect
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -94,6 +94,7 @@ end_per_group(_GroupName, Config) ->
?comp(cover_v3_kernel_5).
?comp(non_variable_apply).
?comp(name_capture).
+?comp(fun_letrec_effect).
try_it(Mod, Conf) ->
Src = filename:join(proplists:get_value(data_dir, Conf),
diff --git a/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core
new file mode 100644
index 0000000000..ab6f5b7940
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core
@@ -0,0 +1,25 @@
+module 'fun_letrec_effect' ['fun_letrec_effect'/0, 'ok'/0, 'wat'/0]
+attributes []
+
+'fun_letrec_effect'/0 =
+ fun () ->
+ do apply 'wat'/0()
+ receive
+ <'bar'> when 'true' -> 'ok'
+ <_0> when 'true' -> 'failed'
+ after 'infinity' ->
+ 'true'
+
+%% The return value (bar) of the fun was optimized away because the result of
+%% the `letrec ... in` was unused, despite the fun's return value being
+%% relevant for the side-effect of the expression.
+'wat'/0 =
+ fun () ->
+ let <Self> = call 'erlang':'self'() in
+ do letrec 'f'/0 = fun () ->
+ do call 'maps':'put'('foo', 'bar', ~{}~)
+ 'bar'
+ in call 'erlang':'send'(Self, apply 'f'/0())
+ 'undefined'
+
+end
diff --git a/lib/compiler/test/core_alias_SUITE.erl b/lib/compiler/test/core_alias_SUITE.erl
index f3f15ef0f8..4f96576621 100644
--- a/lib/compiler/test/core_alias_SUITE.erl
+++ b/lib/compiler/test/core_alias_SUITE.erl
@@ -28,7 +28,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -36,6 +35,7 @@ groups() ->
[tuples, cons]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index dfff8236e8..30d145582a 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -28,7 +28,7 @@
mixed_matching_clauses/1,unnecessary_building/1,
no_no_file/1,configuration/1,supplies/1,
redundant_stack_frame/1,export_from_case/1,
- empty_values/1]).
+ empty_values/1,cover_letrec_effect/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -37,7 +37,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -49,10 +48,11 @@ groups() ->
mixed_matching_clauses,unnecessary_building,
no_no_file,configuration,supplies,
redundant_stack_frame,export_from_case,
- empty_values]}].
+ empty_values,cover_letrec_effect]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -278,6 +278,8 @@ coverage(Config) when is_list(Config) ->
a = cover_remove_non_vars_alias({a,b,c}),
error = cover_will_match_lit_list(),
{ok,[a]} = cover_is_safe_bool_expr(a),
+ false = cover_is_safe_bool_expr2(a),
+ ok = cover_eval_is_function(fun id/1),
ok = cover_opt_guard_try(#cover_opt_guard_try{list=[a]}),
error = cover_opt_guard_try(#cover_opt_guard_try{list=[]}),
@@ -341,6 +343,15 @@ cover_is_safe_bool_expr(X) ->
false
end.
+cover_is_safe_bool_expr2(X) ->
+ try
+ V = [X],
+ is_function(V, 1)
+ catch
+ _:_ ->
+ false
+ end.
+
cover_opt_guard_try(Msg) ->
if
length(Msg#cover_opt_guard_try.list) =/= 1 ->
@@ -349,6 +360,12 @@ cover_opt_guard_try(Msg) ->
ok
end.
+cover_eval_is_function(X) ->
+ case X of
+ {a,_} -> is_function(X);
+ _ -> ok
+ end.
+
bsm_an_inlined(<<_:8>>, _) -> ok;
bsm_an_inlined(_, _) -> error.
@@ -598,5 +615,25 @@ empty_values(_Config) ->
do_empty_values() when (#{})#{} ->
c.
+cover_letrec_effect(_Config) ->
+ self() ! {tag,42},
+ _ = try
+ try
+ ignore
+ after
+ receive
+ {tag,Int}=Term ->
+ Res = #{k => {Term,<<Int:16>>}},
+ self() ! Res
+ end
+ end
+ after
+ ok
+ end,
+ receive
+ Any ->
+ #{k := {{tag,42},<<42:16>>}} = Any
+ end,
+ ok.
id(I) -> I.
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index 01c779b181..da291bdc8b 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,6 +39,7 @@ groups() ->
transforms,maps_warnings,bad_utf8]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 08c3dd8593..39867021cb 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -27,7 +27,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[pending, bif_calls, math_functions,
mixed_float_and_int].
@@ -35,6 +34,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 17bd1656f8..e00885fcd6 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -41,6 +40,7 @@ groups() ->
eep37_dup,badarity,badfun]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 0d6f8c6f98..99dc06b525 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -41,7 +41,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -59,6 +58,7 @@ groups() ->
cover_beam_dead]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index ae59cc8026..fdf2fe88b4 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -42,6 +41,7 @@ groups() ->
coverage]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
{ok,Node} = start_node(compiler, Pa),
[{testing_node,Node}|Config].
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index 2801a7fda4..c80b7cc59e 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -33,7 +33,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -48,6 +47,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 6badc7a8b8..c004dca834 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -76,7 +76,6 @@
suite() -> [].
all() ->
- test_lib:recompile(?MODULE),
[
%% literals
t_build_and_match_literals, t_build_and_match_literals_large,
@@ -130,8 +129,12 @@ all() ->
groups() -> [].
-init_per_suite(Config) -> Config.
-end_per_suite(_Config) -> ok.
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
init_per_group(_GroupName, Config) -> Config.
end_per_group(_GroupName, Config) -> Config.
@@ -706,6 +709,12 @@ t_map_get(Config) when is_list(Config) ->
{'EXIT',{{badmap,[]},_}} = (catch map_get(a, [])),
{'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_get(a, <<1,2,3>>)),
{'EXIT',{{badmap,1},_}} = (catch map_get(a, 1)),
+
+ %% Test that beam_validator understands that NewMap is
+ %% a map after seeing map_get(a, NewMap).
+ NewMap = id(#{a=>b}),
+ b = map_get(a, NewMap),
+ #{a:=z} = NewMap#{a:=z},
ok.
check_map_value(Map, Key, Value) when map_get(Key, Map) =:= Value -> true;
@@ -1203,10 +1212,25 @@ t_guard_bifs(Config) when is_list(Config) ->
true = map_guard_empty_2(),
true = map_guard_head(#{a=>1}),
false = map_guard_head([]),
+
true = map_get_head(#{a=>1}),
+ false = map_get_head(#{}),
+ false = map_get_head([]),
+
+ true = map_get_head_not(#{a=>false}),
+ false = map_get_head_not(#{a=>true}),
+ false = map_get_head(#{}),
false = map_get_head([]),
+
true = map_is_key_head(#{a=>1}),
false = map_is_key_head(#{}),
+ false = map_is_key_head(not_a_map),
+
+ false = map_is_key_head_not(#{a=>1}),
+ true = map_is_key_head_not(#{b=>1}),
+ true = map_is_key_head_not(#{}),
+ false = map_is_key_head_not(not_a_map),
+
true = map_guard_body(#{a=>1}),
false = map_guard_body({}),
true = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }),
@@ -1215,6 +1239,25 @@ t_guard_bifs(Config) when is_list(Config) ->
true = map_guard_ill_map_size(),
true = map_field_check_sequence(#{a=>1}),
false = map_field_check_sequence(#{}),
+
+ %% The guard BIFs used in a body.
+
+ v = map_get(a, id(#{a=>v})),
+ {'EXIT',{{badkey,a},_}} =
+ (catch map_get(a, id(#{}))),
+ {'EXIT',{{badmap,not_a_map},_}} =
+ (catch map_get(a, id(not_a_map))),
+
+ true = is_map_key(a, id(#{a=>1})),
+ false = is_map_key(b, id(#{a=>1})),
+ false = is_map_key(b, id(#{})),
+ {'EXIT',{{badmap,not_a_map},_}} =
+ (catch is_map_key(b, id(not_a_map))),
+
+ {true,v} = erl_699(#{k=>v}),
+ {'EXIT',{{badkey,k},_}} = (catch erl_699(#{})),
+ {'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)),
+
ok.
map_guard_empty() when is_map(#{}); false -> true.
@@ -1227,8 +1270,14 @@ map_guard_head(_) -> false.
map_get_head(M) when map_get(a, M) =:= 1 -> true;
map_get_head(_) -> false.
+map_get_head_not(M) when not map_get(a, M) -> true;
+map_get_head_not(_) -> false.
+
map_is_key_head(M) when is_map_key(a, M) -> true;
-map_is_key_head(M) -> false.
+map_is_key_head(_) -> false.
+
+map_is_key_head_not(M) when not is_map_key(a, M) -> true;
+map_is_key_head_not(_) -> false.
map_guard_body(M) -> is_map(M).
@@ -1245,6 +1294,10 @@ map_field_check_sequence(M)
map_field_check_sequence(_) ->
false.
+erl_699(M) ->
+ %% Used to cause an internal consistency failure.
+ {is_map_key(k, M),maps:get(k, M)}.
+
t_guard_sequence(Config) when is_list(Config) ->
{1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}),
{2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}),
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 88a96d1ca9..e3f842b668 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -45,6 +44,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index a87a2252b7..a1d931b994 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -61,7 +61,6 @@ suite() ->
-spec all() -> misc_SUITE_test_cases().
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -70,6 +69,7 @@ groups() ->
confused_literals,integer_encoding,override_bif]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/overridden_bif_SUITE.erl b/lib/compiler/test/overridden_bif_SUITE.erl
index ce18916515..a46abe8dcf 100644
--- a/lib/compiler/test/overridden_bif_SUITE.erl
+++ b/lib/compiler/test/overridden_bif_SUITE.erl
@@ -36,7 +36,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -45,6 +44,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index fe875abddb..4219768d6f 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -25,7 +25,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1,
- wait/1]).
+ wait/1,recv_in_try/1,double_recv/1]).
-include_lib("common_test/include/ct.hrl").
@@ -40,15 +40,16 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
[{p,test_lib:parallel(),
- [recv,coverage,otp_7980,ref_opt,export,wait]}].
+ [recv,coverage,otp_7980,ref_opt,export,wait,
+ recv_in_try,double_recv]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -305,4 +306,76 @@ wait_1(r, _, _) ->
wait_1(A, B, C) ->
{A,B,C}.
+recv_in_try(_Config) ->
+ self() ! {ok,fh}, {ok,fh} = recv_in_try(infinity, native),
+ self() ! {ok,ignored}, {ok,42} = recv_in_try(infinity, plain),
+ self() ! {error,ignored}, nok = recv_in_try(infinity, plain),
+ timeout = recv_in_try(1, plain),
+ ok.
+
+recv_in_try(Timeout, Format) ->
+ try
+ receive
+ {Status,History} ->
+ %% {test,is_tuple,{f,148},[{x,0}]}.
+ %% {test,test_arity,{f,148},[{x,0},2]}.
+ %% {get_tuple_element,{x,0},0,{y,1}}. %y1 is fragile.
+ %%
+ %% %% Here the fragility of y1 would be be progated to
+ %% %% the 'catch' below. Incorrect, since get_tuple_element
+ %% %% can't fail.
+ %% {get_tuple_element,{x,0},1,{x,2}}.
+ %%
+ %% remove_message. %y1 fragility cleared.
+ FH = case Format of
+ native ->
+ id(History);
+ plain ->
+ id(42)
+ end,
+ case Status of
+ ok ->
+ {ok,FH};
+ error ->
+ nok
+ end
+ after Timeout ->
+ timeout
+ end
+ catch
+ %% The fragility of y1 incorrectly propagated to here.
+ %% beam_validator would complain.
+ throw:{error,Reason} ->
+ {nok,Reason}
+ end.
+
+%% ERL-703. The compiler would crash because beam_utils:anno_defs/1
+%% failed to take into account that code after loop_rec_end is
+%% unreachable.
+
+double_recv(_Config) ->
+ self() ! {more,{a,term}},
+ ok = do_double_recv({more,{a,term}}, any),
+ self() ! message,
+ ok = do_double_recv(whatever, message),
+
+ error = do_double_recv({more,42}, whatever),
+ error = do_double_recv(whatever, whatever),
+ ok.
+
+do_double_recv({more, Rest}, _Msg) ->
+ receive
+ {more, Rest} ->
+ ok
+ after 0 ->
+ error
+ end;
+do_double_recv(_, Msg) ->
+ receive
+ Msg ->
+ ok
+ after 0 ->
+ error
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 5546765f26..118e0a241c 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -41,7 +41,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -52,6 +51,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/regressions_SUITE.erl b/lib/compiler/test/regressions_SUITE.erl
index 7a6fe08c73..f448d54933 100644
--- a/lib/compiler/test/regressions_SUITE.erl
+++ b/lib/compiler/test/regressions_SUITE.erl
@@ -21,13 +21,29 @@
-module(regressions_SUITE).
-include_lib("common_test/include/ct.hrl").
--export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,suite/0]).
+-export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2,
+ suite/0]).
-export([maps/1]).
groups() ->
[{p,test_lib:parallel(),
[maps]}].
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
init_per_testcase(_Case, Config) ->
Config.
@@ -39,7 +55,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
%%% test cases
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 5528af3f3c..1b7ef4ddb0 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -34,7 +34,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -48,6 +47,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 857995b6a6..42ff4f6133 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -55,7 +55,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -68,6 +67,7 @@ groups() ->
underscore,no_warnings,bit_syntax,inlining]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/z_SUITE.erl b/lib/compiler/test/z_SUITE.erl
index 150ab26ff8..bfa8e279e8 100644
--- a/lib/compiler/test/z_SUITE.erl
+++ b/lib/compiler/test/z_SUITE.erl
@@ -26,13 +26,13 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[loaded].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index a26cb09dff..355113a94d 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.2
+COMPILER_VSN = 7.2.3
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 6eeebb67a2..68d2c44b5e 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -179,6 +179,7 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
# ifndef HAS_LIBRESSL
# define HAVE_CHACHA20_POLY1305
+# define HAVE_RSA_OAEP_MD
# endif
#endif
@@ -1341,11 +1342,101 @@ static void init_algorithms_types(ErlNifEnv* env)
// Non-validated algorithms follow
algo_mac_fips_cnt = algo_mac_cnt;
-
// Validated algorithms first
algo_curve_cnt = 0;
+#if defined(HAVE_EC)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp384r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp521r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime256v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls7");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls9");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls12");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512t1");
+#if !defined(OPENSSL_NO_EC2M)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect239k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb176v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb208w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb272w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb304w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb359v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb368w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb431r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls5");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls10");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls11");
+#endif
+#endif
// Non-validated algorithms follow
algo_curve_fips_cnt = algo_curve_cnt;
+#if defined(HAVE_EC)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls6");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls8");
+#if !defined(OPENSSL_NO_EC2M)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls4");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec4");
+#endif
+#endif
//--
#ifdef HAVE_EDDH
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519");
@@ -3810,7 +3901,7 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
int i;
EC_GROUP *group;
const BIGNUM *priv_key;
- EC_POINT *my_ecpoint;
+ EC_POINT *my_ecpoint = NULL;
EC_KEY *other_ecdh = NULL;
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index aa987d2b39..2148062e78 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -89,6 +89,7 @@ debug opt valgrind:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 42e411a0e3..85d5ccaa34 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -830,7 +830,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</p>
<note>
<p>
- The state returned from this function can not be used
+ The state returned from this function cannot be used
to get a reproducable random sequence as from
the other
<seealso marker="stdlib:rand">rand</seealso>
@@ -920,7 +920,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</p>
<note>
<p>
- The state returned from this function can not be used
+ The state returned from this function cannot be used
to get a reproducable random sequence as from
the other
<seealso marker="stdlib:rand">rand</seealso>
diff --git a/lib/crypto/doc/src/engine_keys.xml b/lib/crypto/doc/src/engine_keys.xml
index 38714fed8a..80d811c47e 100644
--- a/lib/crypto/doc/src/engine_keys.xml
+++ b/lib/crypto/doc/src/engine_keys.xml
@@ -40,7 +40,7 @@
</p>
<p>
An engine could among other tasks provide a storage for
- private or public keys. Such a storage could be made safer than the normal file system. Thoose techniques are not
+ private or public keys. Such a storage could be made safer than the normal file system. Those techniques are not
described in this User's Guide. Here we concentrate on how to use private or public keys stored in
such an engine.
</p>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 2e48b48d67..5e0851f6b8 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,22 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a node crash in <c>crypto:compute_key(ecdh,
+ ...)</c> when passing a wrongly typed Others
+ argument.</p>
+ <p>
+ Own Id: OTP-15194 Aux Id: ERL-673 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -78,6 +94,22 @@
</section>
+<section><title>Crypto 4.2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a node crash in <c>crypto:compute_key(ecdh,
+ ...)</c> when passing a wrongly typed Others
+ argument.</p>
+ <p>
+ Own Id: OTP-15194 Aux Id: ERL-673 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 714cba58b9..835cadce47 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -108,17 +108,11 @@ stop() ->
supports()->
{Hashs, PubKeys, Ciphers, Macs, Curves} = algorithms(),
-
[{hashs, Hashs},
{ciphers, Ciphers},
{public_keys, PubKeys},
- {macs, Macs}
- | case Curves of
- [] -> [];
- _ -> [{curves, Curves}] % Only show this experimental feature
- % if OpenSSL 1.1.1 beta4 or higher (where
- % eddsa and eddh is enabled)
- end
+ {macs, Macs},
+ {curves, Curves}
].
info_lib() -> ?nif_stub.
diff --git a/lib/crypto/src/crypto_ec_curves.erl b/lib/crypto/src/crypto_ec_curves.erl
index 9602a7e24b..a0a2f99601 100644
--- a/lib/crypto/src/crypto_ec_curves.erl
+++ b/lib/crypto/src/crypto_ec_curves.erl
@@ -3,41 +3,7 @@
-export([curve/1, curves/0]).
curves() ->
- CryptoSupport = crypto:supports(),
- PubKeys = proplists:get_value(public_keys, CryptoSupport),
- HasEC = proplists:get_bool(ecdh, PubKeys),
- HasGF2m = proplists:get_bool(ec_gf2m, PubKeys),
- FIPSMode = crypto:info_fips() == enabled,
- prime_curves(HasEC, FIPSMode) ++ characteristic_two_curves(HasGF2m, FIPSMode).
-
-
-prime_curves(true, true) ->
- [secp160k1,secp160r1,secp160r2,
- secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1,
- secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,
- prime256v1,wtls7,wtls9,wtls12,
- brainpoolP160r1,brainpoolP160t1,brainpoolP192r1,brainpoolP192t1,
- brainpoolP224r1,brainpoolP224t1,brainpoolP256r1,brainpoolP256t1,
- brainpoolP320r1,brainpoolP320t1,brainpoolP384r1,brainpoolP384t1,
- brainpoolP512r1,brainpoolP512t1];
-prime_curves(true, false) ->
- [secp112r1,secp112r2,secp128r1,secp128r2,wtls6,wtls8]
- ++ prime_curves(true, true);
-prime_curves(_, _) ->
- [].
-
-characteristic_two_curves(true, true) ->
- [sect163k1,sect163r1,
- sect163r2,sect193r1,sect193r2,sect233k1,sect233r1,sect239k1,sect283k1,
- sect283r1,sect409k1,sect409r1,sect571k1,sect571r1,c2pnb163v1,c2pnb163v2,
- c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,
- c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359v1,c2pnb368w1,c2tnb431r1,
- wtls3,wtls5,wtls10,wtls11];
-characteristic_two_curves(true, _) ->
- [sect113r1,sect113r2,sect131r1,sect131r2,wtls1,wtls4,ipsec3,ipsec4]
- ++ characteristic_two_curves(true, true);
-characteristic_two_curves(_, _) ->
- [].
+ proplists:get_value(curves, crypto:supports()) -- [x25519,x448].
curve(secp112r1) ->
{
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index ebb55c4a34..1027a8d945 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -31,6 +31,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app,
+ {group, api_errors},
appup,
{group, fips},
{group, non_fips},
@@ -133,7 +134,7 @@ groups() ->
]},
{dh, [], [generate_compute,
compute_bug]},
- {ecdh, [], [compute, generate]},
+ {ecdh, [], [generate_all_supported, compute, generate]},
{srp, [], [generate_compute]},
{des_cbc, [], [block]},
{des_cfb, [], [block]},
@@ -170,7 +171,8 @@ groups() ->
{no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
{no_rc2_cbc, [], [no_support, no_block]},
- {no_rc4, [], [no_support, no_stream]}
+ {no_rc4, [], [no_support, no_stream]},
+ {api_errors, [], [api_errors_ecdh]}
].
%%-------------------------------------------------------------------
@@ -205,7 +207,7 @@ init_per_suite(Config) ->
Config
end
catch _:_ ->
- {skip, "Crypto did not start"}
+ {fail, "Crypto did not start"}
end.
end_per_suite(_Config) ->
@@ -238,6 +240,8 @@ init_per_group(non_fips, Config) ->
_NotEnabled ->
NonFIPSConfig
end;
+init_per_group(api_errors, Config) ->
+ Config;
init_per_group(GroupName, Config) ->
case atom_to_list(GroupName) of
"no_" ++ TypeStr ->
@@ -506,6 +510,33 @@ compute(Config) when is_list(Config) ->
Gen = proplists:get_value(compute, Config),
lists:foreach(fun do_compute/1, Gen).
%%--------------------------------------------------------------------
+generate_all_supported() ->
+ [{doc, " Test that all curves from crypto:ec_curves/0 returns two binaries"}].
+generate_all_supported(_Config) ->
+ Results =
+ [try
+ crypto:generate_key(ecdh, C)
+ of
+ {B1,B2} when is_binary(B1) and is_binary(B2) ->
+ %% That is, seems like it works as expected.
+ {ok,C};
+ Err ->
+ ct:log("ERROR: Curve ~p generated ~p", [C,Err]),
+ {error,{C,Err}}
+ catch
+ Cls:Err:Stack ->
+ ct:log("ERROR: Curve ~p exception ~p:~p~n~p", [C,Cls,Err,Stack]),
+ {error,{C,{Cls,Err}}}
+ end
+ || C <- crypto:ec_curves()
+ ],
+ OK = [C || {ok,C} <- Results],
+ ct:log("Ok (len=~p): ~p", [length(OK), OK]),
+ false = lists:any(fun({error,_}) -> true;
+ (_) -> false
+ end, Results).
+
+%%--------------------------------------------------------------------
generate() ->
[{doc, " Test crypto:generate_key"}].
generate(Config) when is_list(Config) ->
@@ -811,7 +842,7 @@ do_sign_verify({Type, Hash, Public, Private, Msg, Options}) ->
error:notsup when NotSupLow == true,
is_integer(LibVer),
LibVer < 16#10001000 ->
- %% Thoose opts where introduced in 1.0.1
+ %% Those opts where introduced in 1.0.1
ct:log("notsup but OK in old cryptolib crypto:sign(~p, ~p, ..., ..., ..., ~p)",
[Type,Hash,Options]),
true;
@@ -836,26 +867,69 @@ negative_verify(Type, Hash, Msg, Signature, Public, Options) ->
ok
end.
+-define(PUB_PRIV_ENC_DEC_CATCH(Type,Padding),
+ CC:EE ->
+ ct:log("~p:~p in ~p:~p/~p, line ~p.~n"
+ "Type = ~p~nPadding = ~p",
+ [CC,EE,?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY,?LINE,(Type),(Padding)]),
+ MaybeUnsupported =
+ case crypto:info_lib() of
+ [{<<"OpenSSL">>,_,_}] ->
+ is_list(Padding) andalso
+ lists:any(fun(P) -> lists:member(P,(Padding)) end,
+ [{rsa_padding, rsa_pkcs1_oaep_padding},
+ {rsa_padding, rsa_sslv23_padding},
+ {rsa_padding, rsa_x931_padding}]);
+ _ ->
+ false
+ end,
+ case CC of
+ error when MaybeUnsupported ->
+ ct:comment("Padding unsupported?",[]);
+ _ ->
+ ct:fail({?FUNCTION_NAME,CC,EE,(Type),(Padding)})
+ end
+ ).
+
do_public_encrypt({Type, Public, Private, Msg, Padding}) ->
- PublicEcn = (catch crypto:public_encrypt(Type, Msg, Public, Padding)),
- case crypto:private_decrypt(Type, PublicEcn, Private, Padding) of
- Msg ->
- ok;
- Other ->
- ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, Other}})
+ try
+ crypto:public_encrypt(Type, Msg, Public, Padding)
+ of
+ PublicEcn ->
+ try
+ crypto:private_decrypt(Type, PublicEcn, Private, Padding)
+ of
+ Msg ->
+ ok;
+ Other ->
+ ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, Other}})
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
+ end
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
end.
-do_private_encrypt({_Type, _Public, _Private, _Msg, rsa_pkcs1_oaep_padding}) ->
- ok; %% Not supported by openssl
+
do_private_encrypt({Type, Public, Private, Msg, Padding}) ->
- PrivEcn = (catch crypto:private_encrypt(Type, Msg, Private, Padding)),
- case crypto:public_decrypt(Type, PrivEcn, Public, Padding) of
- Msg ->
- ok;
- Other ->
- ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, Other}})
+ try
+ crypto:private_encrypt(Type, Msg, Private, Padding)
+ of
+ PrivEcn ->
+ try
+ crypto:public_decrypt(Type, PrivEcn, Public, Padding)
+ of
+ Msg ->
+ ok;
+ Other ->
+ ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, Other}})
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
+ end
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
end.
-
+
do_generate_compute({srp = Type, UserPrivate, UserGenParams, UserComParams,
HostPublic, HostPrivate, HostGenParams, HostComParam, SessionKey}) ->
{UserPublic, UserPrivate} = crypto:generate_key(Type, UserGenParams, UserPrivate),
@@ -1241,7 +1315,12 @@ group_config(rsa = Type, Config) ->
end,
MsgPubEnc = <<"7896345786348 Asldi">>,
PubPrivEnc = [{rsa, PublicS, PrivateS, MsgPubEnc, rsa_pkcs1_padding},
+ {rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_pkcs1_padding}]},
+ {rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_sslv23_padding}]},
+ {rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_x931_padding}]},
rsa_oaep(),
+ rsa_oaep_label(),
+ rsa_oaep256(),
no_padding()
],
Generate = [{rsa, 1024, 3}, {rsa, 2048, 17}, {rsa, 3072, 65537}],
@@ -2334,7 +2413,32 @@ rsa_oaep() ->
hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
%%Msg = hexstr2bin("6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34"),
Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
- {rsa, Public, Private, Msg, rsa_pkcs1_oaep_padding}.
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}]}.
+
+rsa_oaep_label() ->
+ Public = [hexstr2bin("010001"),
+ hexstr2bin("a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb")],
+ Private = Public ++ [hexstr2bin("53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"),
+ hexstr2bin("d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d"),
+ hexstr2bin("cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77"),
+ hexstr2bin("0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1"),
+ hexstr2bin("95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583"),
+ hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
+ Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
+ Lbl = hexstr2bin("1332a67ca7088f75c9b8fb5e3d072882"),
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}, {rsa_oaep_label, Lbl}]}.
+
+rsa_oaep256() ->
+ Public = [hexstr2bin("010001"),
+ hexstr2bin("a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb")],
+ Private = Public ++ [hexstr2bin("53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"),
+ hexstr2bin("d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d"),
+ hexstr2bin("cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77"),
+ hexstr2bin("0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1"),
+ hexstr2bin("95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583"),
+ hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
+ Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}, {rsa_oaep_md, sha256}]}.
ecc() ->
%% http://point-at-infinity.org/ecc/nisttv
@@ -2510,3 +2614,14 @@ parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
I ->
parse_rsp(Type, Next, [{Type, Key, Msg, I, MAC}|Acc])
end.
+
+api_errors_ecdh(Config) when is_list(Config) ->
+ %% Check that we don't segfault when fed garbage.
+ Test = fun(Others, Curve) ->
+ {_Pub, Priv} = crypto:generate_key(ecdh, Curve),
+ crypto:compute_key(ecdh, Others, Priv, Curve)
+ end,
+ Others = [gurka, 0, <<0>>],
+ Curves = [gaffel, 0, sect571r1],
+ [_= (catch Test(O, C)) || O <- Others, C <- Curves],
+ ok.
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index f708d7272d..bb9aa49b50 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -425,7 +425,7 @@ ctrl_cmd_string_optional(Config) when is_list(Config) ->
end.
%%%----------------------------------------------------------------
-%%% Pub/priv key storage tests. Thoose are for testing the crypto.erl
+%%% Pub/priv key storage tests. Those are for testing the crypto.erl
%%% support for using priv/pub keys stored in an engine.
sign_verify_rsa(Config) ->
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index cc34c20ac6..0d7b0e5575 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.3
+CRYPTO_VSN = 4.3.1
diff --git a/lib/debugger/doc/src/Makefile b/lib/debugger/doc/src/Makefile
index 4a25006ee0..56d6085e9c 100644
--- a/lib/debugger/doc/src/Makefile
+++ b/lib/debugger/doc/src/Makefile
@@ -99,6 +99,7 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl
index ac901c5469..0eb258567f 100644
--- a/lib/debugger/src/dbg_icmd.erl
+++ b/lib/debugger/src/dbg_icmd.erl
@@ -248,7 +248,7 @@ handle_int_msg({attached, AttPid}, Status, _Bs,
tell_attached({attached, M, Line, get(trace)}),
%% Give info about status and call level as well
- %% In this case, Status can not be exit_at
+ %% In this case, Status cannot be exit_at
Msg = case Status of
idle -> {func_at,M,Line,Le};
break -> {break_at,M,Line,Le};
diff --git a/lib/dialyzer/doc/src/Makefile b/lib/dialyzer/doc/src/Makefile
index 3463b589e6..3ce777392b 100644
--- a/lib/dialyzer/doc/src/Makefile
+++ b/lib/dialyzer/doc/src/Makefile
@@ -91,6 +91,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/dialyzer/src/typer.erl b/lib/dialyzer/src/typer.erl
index 4b99f5f72e..5a1b8619c9 100644
--- a/lib/dialyzer/src/typer.erl
+++ b/lib/dialyzer/src/typer.erl
@@ -980,7 +980,7 @@ fatal_error(Slogan) ->
mode_error(OldMode, NewMode) ->
Msg = io_lib:format("Mode was previously set to '~s'; "
- "can not set it to '~s' now",
+ "cannot set it to '~s' now",
[OldMode, NewMode]),
fatal_error(Msg).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
index ea92613781..3606b21932 100644
--- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
@@ -272,7 +272,7 @@ valfun_1(if_end, Vst) ->
valfun_1({try_case_end,Src}, Vst) ->
assert_term(Src, Vst),
kill_state(Vst);
-%% Instructions that can not cause exceptions
+%% Instructions that cannot cause exceptions
valfun_1({move,Src,Dst}, Vst) ->
Type = get_term_type(Src, Vst),
set_type_reg(Type, Dst, Vst);
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl
index 1d065b3723..88b464a721 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber.erl
@@ -300,7 +300,7 @@ gen_encode_prim(_Erules,D,DoTag,Value) when record(D,type) ->
'ASN1_OPEN_TYPE' ->
emit_encode_func('open_type', Value,DoTag);
XX ->
- exit({'can not encode' ,XX})
+ exit({'cannot encode' ,XX})
end.
@@ -562,7 +562,7 @@ gen_dec_prim(Erules,Att,BytesVar,DoTag,TagIn,Length,_Form,OptOrMand) ->
BytesVar,","]),
false;
Other ->
- exit({'can not decode' ,Other})
+ exit({'cannot decode' ,Other})
end,
NewLength = case DoLength of
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
index 9164ec6551..573bb15c92 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen_ber_bin_v2.erl
@@ -290,7 +290,7 @@ gen_encode_prim(_Erules,D,DoTag,Value) when record(D,type) ->
'ASN1_OPEN_TYPE' ->
emit_encode_func('open_type', Value,DoTag);
XX ->
- exit({'can not encode' ,XX})
+ exit({'cannot encode' ,XX})
end.
@@ -602,7 +602,7 @@ gen_dec_prim(_Erules,Att,BytesVar,DoTag,_TagIn,_Form,_OptOrMand) ->
BytesVar,","]),
add_func({decode_open_type_as_binary,2});
Other ->
- exit({'can not decode' ,Other})
+ exit({'cannot decode' ,Other})
end,
case {DoTag,NewTypeName} of
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl
index 4008f8d789..9e0cdac2dc 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_lib.erl
@@ -779,7 +779,7 @@ error_desc(no_transaction) -> "Operation not allowed outside transactions";
error_desc(combine_error) -> "Table options were ilegally combined";
error_desc(bad_index) -> "Index already exists or was out of bounds";
error_desc(already_exists) -> "Some schema option we try to set is already on";
-error_desc(index_exists)-> "Some ops can not be performed on tabs with index";
+error_desc(index_exists)-> "Some ops cannot be performed on tabs with index";
error_desc(no_exists)-> "Tried to perform op on non-existing (non alive) item";
error_desc(system_limit) -> "Some system_limit was exhausted";
error_desc(mnesia_down) -> "A transaction involving objects at some remote "
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
index af49ceff72..b4e9edb7ce 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
@@ -1529,7 +1529,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
case catch mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
{Modified, C, DumperMode} when record(C, commit) ->
- %% If we can not find any local unclear decision
+ %% If we cannot find any local unclear decision
%% we should presume abort at startup recovery
case lists:member(node(), DiscNs) of
false ->
diff --git a/lib/dialyzer/test/small_SUITE_data/results/maps_sum b/lib/dialyzer/test/small_SUITE_data/results/maps_sum
index b29ac77d88..daa099e490 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/maps_sum
+++ b/lib/dialyzer/test/small_SUITE_data/results/maps_sum
@@ -1,4 +1,4 @@
-maps_sum.erl:15: Invalid type specification for function maps_sum:wrong1/1. The success typing is (maps:iterator() | map()) -> any()
+maps_sum.erl:15: Invalid type specification for function maps_sum:wrong1/1. The success typing is (maps:iterator(_,_) | map()) -> any()
maps_sum.erl:26: Function wrong2/1 has no local return
maps_sum.erl:27: The call lists:foldl(fun((_,_,_) -> any()),0,Data::any()) will never return since it differs in the 1st argument from the success typing arguments: (fun((_,_) -> any()),any(),[any()])
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 7a7546fc4d..7672598060 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -77,6 +77,7 @@ clean_man:
clean_html:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile
index 71de42795a..aba94a6802 100644
--- a/lib/edoc/doc/src/Makefile
+++ b/lib/edoc/doc/src/Makefile
@@ -114,6 +114,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/eldap/doc/src/Makefile b/lib/eldap/doc/src/Makefile
index aff1da4a9a..bf1eca267a 100644
--- a/lib/eldap/doc/src/Makefile
+++ b/lib/eldap/doc/src/Makefile
@@ -89,6 +89,7 @@ debug opt valgrind:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/erl_docgen/doc/src/Makefile b/lib/erl_docgen/doc/src/Makefile
index a9110e4635..d6d2550425 100644
--- a/lib/erl_docgen/doc/src/Makefile
+++ b/lib/erl_docgen/doc/src/Makefile
@@ -106,6 +106,7 @@ html: gifs examples $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
index b065c18cda..d562cfddcc 100644
--- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
+++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
@@ -182,7 +182,7 @@ chapter_title(#xmlElement{content=Es}) -> % name = h3 | h4
%% otp_xmlify(Es1) -> Es2
%% Es1 = Es2 = [#xmlElement{} | #xmlText{}]
%% Fix things that are allowed in XHTML but not in chapter/erlref DTDs.
-%% 1) lists (<ul>, <ol>, <dl>) and code snippets (<pre>) can not occur
+%% 1) lists (<ul>, <ol>, <dl>) and code snippets (<pre>) cannot occur
%% within a <p>, such a <p> must be splitted into a sequence of <p>,
%% <ul>, <ol>, <dl> and <pre>.
%% 2) <a> must only have either a href attribute (corresponds to a
diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile
index 8ef7e9648c..173bd2e83b 100644
--- a/lib/erl_interface/doc/src/Makefile
+++ b/lib/erl_interface/doc/src/Makefile
@@ -100,6 +100,7 @@ debug opt:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 5b81f795b2..1438317d8d 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -69,6 +69,24 @@
</section>
+<section><title>Erl_Interface 3.10.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make <c>ei_connect</c> and friends also accept state
+ <c>ok_simultaneous</c> during handshake, which means the
+ other node has initiated a connection setup that will be
+ cancelled in favor of this connection.</p>
+ <p>
+ Own Id: OTP-15161 Aux Id: ERIERL-191 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/src/INSTALL b/lib/erl_interface/src/INSTALL
index b42a17ac46..bf3ca8b6a5 100644
--- a/lib/erl_interface/src/INSTALL
+++ b/lib/erl_interface/src/INSTALL
@@ -122,10 +122,10 @@ you can use the `configure' options `--x-includes=DIR' and
Specifying the System Type
==========================
- There may be some features `configure' can not figure out
+ There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
-a message saying it can not guess the host type, give it the
+a message saying it cannot guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index f5034ca3e8..9df4fa3b6c 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -138,6 +138,11 @@ static int recv_name(int fd,
unsigned *version,
unsigned *flags, ErlConnect *namebuf, unsigned ms);
+static struct hostent*
+dyn_gethostbyname_r(const char *name, struct hostent *hostp, char **buffer_p,
+ int buflen, int *h_errnop);
+
+
/***************************************************************************
*
@@ -480,10 +485,14 @@ int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
int ei_connect_init(ei_cnode* ec, const char* this_node_name,
const char *cookie, short creation)
{
- struct hostent *hp;
char thishostname[EI_MAXHOSTNAMELEN+1];
char thisnodename[MAXNODELEN+1];
char thisalivename[EI_MAXALIVELEN+1];
+ struct hostent host, *hp;
+ char buffer[1024];
+ char *buf = buffer;
+ int ei_h_errno;
+ int res;
#ifdef __WIN32__
if (!initWinSock()) {
@@ -517,10 +526,13 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
strcpy(thisalivename, this_node_name);
}
- if ((hp = ei_gethostbyname(thishostname)) == 0) {
+ hp = dyn_gethostbyname_r(thishostname,&host,&buf,sizeof(buffer),&ei_h_errno);
+ if (hp == NULL) {
/* Looking up IP given hostname fails. We must be on a standalone
host so let's use loopback for communication instead. */
- if ((hp = ei_gethostbyname("localhost")) == 0) {
+ hp = dyn_gethostbyname_r("localhost", &host, &buf, sizeof(buffer),
+ &ei_h_errno);
+ if (hp == NULL) {
#ifdef __WIN32__
char reason[1024];
@@ -549,8 +561,11 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
sprintf(thisnodename, "%s@%s", this_node_name, hp->h_name);
}
}
- return ei_connect_xinit(ec, thishostname, thisalivename, thisnodename,
- (struct in_addr *)*hp->h_addr_list, cookie, creation);
+ res = ei_connect_xinit(ec, thishostname, thisalivename, thisnodename,
+ (struct in_addr *)*hp->h_addr_list, cookie, creation);
+ if (buf != buffer)
+ free(buf);
+ return res;
}
@@ -595,6 +610,13 @@ struct hostent *dyn_gethostbyname_r(const char *name,
int buflen,
int *h_errnop)
{
+#ifdef __WIN32__
+ /*
+ * Apparently ei_gethostbyname_r not implemented for Windows (?)
+ * Fall back on ei_gethostbyname like before.
+ */
+ return ei_gethostbyname(name);
+#else
char* buf = *buffer_p;
struct hostent *hp;
@@ -629,6 +651,7 @@ struct hostent *dyn_gethostbyname_r(const char *name,
}
}
return hp;
+#endif
}
/*
@@ -999,7 +1022,7 @@ int ei_do_receive_msg(int fd, int staticbuffer_p,
erl_errno = EMSGSIZE;
return ERL_ERROR;
}
- x->index = x->buffsz;
+ x->index = msglen;
switch (msg->msgtype) { /* FIXME does not handle trace tokens and monitors */
case ERL_SEND:
case ERL_REG_SEND:
@@ -1357,11 +1380,14 @@ static int recv_status(int fd, unsigned ms)
"<- RECV_STATUS socket read failed (%d)", rlen);
goto error;
}
- if (rlen == 3 && buf[0] == 's' && buf[1] == 'o' &&
- buf[2] == 'k') {
+
+ EI_TRACE_CONN2("recv_status",
+ "<- RECV_STATUS (%.*s)", (rlen>20 ? 20 : rlen), buf);
+
+ if (rlen >= 3 && buf[0] == 's' && buf[1] == 'o' && buf[2] == 'k') {
+ /* Expecting "sok" or "sok_simultaneous" */
if (!is_static)
free(buf);
- EI_TRACE_CONN0("recv_status","<- RECV_STATUS (ok)");
return 0;
}
error:
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
index 25608edeec..8c7e86555d 100644
--- a/lib/erl_interface/src/misc/ei_pthreads.c
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -78,7 +78,7 @@ static void tls_init_once(void)
errno_tls_index = TlsAlloc();
if (errno_tls_index == TLS_OUT_OF_INDEXES) {
fprintf(stderr,
- "FATAL ERROR: can not allocate TLS index for "
+ "FATAL ERROR: cannot allocate TLS index for "
"erl_errno (error code = %d)!\n",GetLastError());
exit(1);
}
@@ -206,6 +206,7 @@ volatile int *__erl_errno_place(void)
use_fallback = 1;
return &fallback_errno;
}
+ *erl_errno_p = 0;
if (pthread_setspecific(erl_errno_key, erl_errno_p) != 0 ||
(erl_errno_p = pthread_getspecific(erl_errno_key)) == NULL) {
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index 85c567acd3..78a433d21b 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_accept_SUITE_data/ei_accept_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
ei_accept/1, ei_threaded_accept/1,
monitor_ei_process/1]).
@@ -38,8 +39,11 @@ all() ->
[ei_accept, ei_threaded_accept,
monitor_ei_process].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
ei_accept(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
@@ -91,7 +95,7 @@ ei_threaded_accept(Config) when is_list(Config) ->
%% Test erlang:monitor toward erl_interface "processes"
monitor_ei_process(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
@@ -99,7 +103,6 @@ monitor_ei_process(Config) when is_list(Config) ->
EINode = list_to_atom("c42@"++Myname),
io:format("EINode ~p ~n", [EINode]),
- Self = self(),
Port = 6543,
{ok, ListenFd} = ei_publish(P, Port),
MRef1 = erlang:monitor(process, {any, EINode}),
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
index 04bba90732..50df848b69 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
@@ -75,11 +75,7 @@ TESTCASE(interpret)
ei_term term;
ei_x_new(&x);
- for (;;) {
- if (get_bin_term(&x, &term)) {
- report(1);
- return;
- } else {
+ while (get_bin_term(&x, &term) == 0) {
char* buf = x.buff, func[MAXATOMLEN];
int index = x.index, arity;
if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
@@ -100,8 +96,9 @@ TESTCASE(interpret)
message("\"%d\" \n", func);
fail("bad command");
}
- }
- }
+ }
+ report(1);
+ ei_x_free(&x);
}
static void cmd_ei_connect_init(char* buf, int len)
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 66498deadc..24cd384295 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_connect_SUITE_data/ei_connect_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
ei_send/1,
ei_reg_send/1,
ei_format_pid/1,
@@ -44,8 +45,11 @@ all() ->
[ei_send, ei_reg_send, ei_rpc, ei_format_pid, ei_send_funs,
ei_threaded_send, ei_set_get_tracelevel].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
ei_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -58,7 +62,7 @@ ei_send(Config) when is_list(Config) ->
ei_format_pid(Config) when is_list(Config) ->
S = self(),
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -70,7 +74,7 @@ ei_format_pid(Config) when is_list(Config) ->
ok.
ei_send_funs(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -88,7 +92,7 @@ ei_send_funs(Config) when is_list(Config) ->
ok.
ei_reg_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -137,7 +141,7 @@ start_einode(Einode, N, Host) ->
ok.
ei_rpc(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -150,7 +154,7 @@ ei_rpc(Config) when is_list(Config) ->
ok.
ei_set_get_tracelevel(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
5 = ei_set_get_tracelevel(P, 5),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 6a3796dd24..fbd86cdb50 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -74,11 +74,7 @@ TESTCASE(interpret)
ei_term term;
ei_x_new(&x);
- for (;;) {
- if (get_bin_term(&x, &term)) {
- report(1);
- return;
- } else {
+ while (get_bin_term(&x, &term) == 0) {
char* buf = x.buff, func[MAXATOMLEN];
int index = x.index, arity;
if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
@@ -99,8 +95,10 @@ TESTCASE(interpret)
message("\"%d\" \n", func);
fail("bad command");
}
- }
- }
+ }
+ report(1);
+ ei_x_free(&x);
+ return;
}
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index 74fb9b8916..499f10611e 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_decode_SUITE_data/ei_decode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_decode_long/1,
test_ei_decode_ulong/1,
test_ei_decode_longlong/1,
@@ -42,6 +43,9 @@ all() ->
test_ei_decode_char, test_ei_decode_nonoptimal,
test_ei_decode_misc, test_ei_decode_utf8_atom].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
% NOTE: for historical reasons we don't pach as tight as we can,
@@ -51,7 +55,7 @@ all() ->
%% ######################################################################## %%
test_ei_decode_long(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_long),
+ P = runner:start(Config, ?test_ei_decode_long),
send_integers(P),
runner:recv_eot(P),
ok.
@@ -60,7 +64,7 @@ test_ei_decode_long(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_ulong(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_ulong),
+ P = runner:start(Config, ?test_ei_decode_ulong),
send_integers(P),
runner:recv_eot(P),
ok.
@@ -77,7 +81,7 @@ test_ei_decode_longlong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_decode_longlong),
+ P = runner:start(Config, ?test_ei_decode_longlong),
send_integers2(P),
runner:recv_eot(P),
ok
@@ -91,7 +95,7 @@ test_ei_decode_ulonglong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_decode_ulonglong),
+ P = runner:start(Config, ?test_ei_decode_ulonglong),
send_integers2(P),
runner:recv_eot(P),
ok
@@ -104,7 +108,7 @@ test_ei_decode_ulonglong(Config) when is_list(Config) ->
%% FIXME maybe the API should change to use "unsigned char" to be clear?!
test_ei_decode_char(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_char),
+ P = runner:start(Config, ?test_ei_decode_char),
send_term_as_binary(P,0),
send_term_as_binary(P,16#7f),
@@ -119,7 +123,7 @@ test_ei_decode_char(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_nonoptimal(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_nonoptimal),
+ P = runner:start(Config, ?test_ei_decode_nonoptimal),
send_non_optimal_pos(P), % decode_char
send_non_optimal(P), % decode_long
@@ -168,7 +172,7 @@ send_non_optimal_neg(P) ->
%% ######################################################################## %%
test_ei_decode_misc(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_misc),
+ P = runner:start(Config, ?test_ei_decode_misc),
send_term_as_binary(P,0.0),
send_term_as_binary(P,-1.0),
@@ -199,7 +203,7 @@ test_ei_decode_misc(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_utf8_atom(Config) ->
- P = runner:start(?test_ei_decode_utf8_atom),
+ P = runner:start(Config, ?test_ei_decode_utf8_atom),
send_latin1_atom_as_binary(P,"å"),
send_latin1_atom_as_binary(P,"ä"),
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index b7a2c4bb8b..5a9be1e9a2 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -105,6 +105,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail1("size of encoded data (%d) is incorrect", size1); \
return; \
} \
+ free_packet(buf); \
} \
#define EI_DECODE_2_FAIL(FUNC,SIZE,TYPE,VAL) \
@@ -148,6 +149,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data should be 0"); \
return; \
} \
+ free_packet(buf); \
} \
#define dump(arr, num) { \
@@ -205,6 +207,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data is incorrect"); \
return; \
} \
+ free_packet(buf); \
} \
#define EI_DECODE_STRING(FUNC,SIZE,VAL) \
@@ -248,6 +251,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data should be 0"); \
return; \
} \
+ free_packet(buf); \
} \
//#define EI_DECODE_UTF8_STRING(FUNC,SIZE,VAL)
@@ -310,6 +314,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data is incorrect"); \
return; \
} \
+ free_packet(buf); \
} \
/* ******************************************************************** */
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 160720b413..6476e92be9 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_decode_encode_SUITE_data/ei_decode_encode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_decode_encode/1]).
suite() ->
@@ -33,6 +34,9 @@ suite() ->
all() ->
[test_ei_decode_encode].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
% NOTE: these types have no meaning on the C side so we pass them
@@ -42,7 +46,7 @@ all() ->
%% ######################################################################## %%
test_ei_decode_encode(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_encode),
+ P = runner:start(Config, ?test_ei_decode_encode),
Fun = fun (X) -> {X,true} end,
Pid = self(),
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index 467f789fdb..6285b5e199 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -466,6 +466,7 @@ void decode_encode_big(struct Type* t)
send_buffer(arg.buff, arg.index);
ei_x_free(&arg);
ei_free_big(p);
+ free_packet(buf);
}
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index 8857b092f3..8c3b0e193b 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_encode_SUITE_data/ei_encode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_encode_long/1,
test_ei_encode_ulong/1,
test_ei_encode_longlong/1,
@@ -45,6 +46,9 @@ all() ->
test_ei_encode_fails, test_ei_encode_utf8_atom,
test_ei_encode_utf8_atom_len].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
@@ -55,7 +59,7 @@ all() ->
%% ######################################################################## %%
test_ei_encode_long(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_long),
+ P = runner:start(Config, ?test_ei_encode_long),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -77,7 +81,7 @@ test_ei_encode_long(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_ulong(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_ulong),
+ P = runner:start(Config, ?test_ei_encode_ulong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -101,7 +105,7 @@ test_ei_encode_longlong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_encode_longlong),
+ P = runner:start(Config, ?test_ei_encode_longlong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -132,7 +136,7 @@ test_ei_encode_ulonglong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_encode_ulonglong),
+ P = runner:start(Config, ?test_ei_encode_ulonglong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -158,7 +162,7 @@ test_ei_encode_ulonglong(Config) when is_list(Config) ->
%% FIXME maybe the API should change to use "unsigned char" to be clear?!
test_ei_encode_char(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_char),
+ P = runner:start(Config, ?test_ei_encode_char),
{<<97, 0>>,0} = get_buf_and_term(P),
{<<97,127>>,16#7f} = get_buf_and_term(P),
@@ -171,7 +175,7 @@ test_ei_encode_char(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_misc(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_misc),
+ P = runner:start(Config, ?test_ei_encode_misc),
<<131>> = get_binaries(P),
@@ -217,7 +221,7 @@ test_ei_encode_misc(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_fails(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_fails),
+ P = runner:start(Config, ?test_ei_encode_fails),
XAtom = list_to_atom(lists:duplicate(255, $x)),
YAtom = list_to_atom(lists:duplicate(255, $y)),
@@ -236,7 +240,7 @@ test_ei_encode_fails(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_utf8_atom(Config) ->
- P = runner:start(?test_ei_encode_utf8_atom),
+ P = runner:start(Config, ?test_ei_encode_utf8_atom),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
@@ -251,7 +255,7 @@ test_ei_encode_utf8_atom(Config) ->
%% ######################################################################## %%
test_ei_encode_utf8_atom_len(Config) ->
- P = runner:start(?test_ei_encode_utf8_atom_len),
+ P = runner:start(Config, ?test_ei_encode_utf8_atom_len),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
{<<119,4,195,133,195,132>>,'ÅÄ'} = get_buf_and_term(P),
diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl
index 07ee479b1f..b11a6ff164 100644
--- a/lib/erl_interface/test/ei_format_SUITE.erl
+++ b/lib/erl_interface/test/ei_format_SUITE.erl
@@ -26,6 +26,7 @@
-export([format_wo_ver/1,
all/0, suite/0,
+ init_per_testcase/2,
atoms/1,
tuples/1,
lists/1]).
@@ -41,10 +42,13 @@ suite() ->
all() ->
[format_wo_ver, atoms, tuples, lists].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, ''} = get_term(P),
{term, 'a'} = get_term(P),
@@ -84,7 +88,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, {}} = get_term(P),
{term, {a}} = get_term(P),
@@ -105,7 +109,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, []} = get_term(P),
{term, [a]} = get_term(P),
@@ -146,7 +150,7 @@ lists(Config) when is_list(Config) ->
format_wo_ver(Config) when is_list(Config) ->
- P = runner:start(?format_wo_ver),
+ P = runner:start(Config, ?format_wo_ver),
{term, [-1, 2, $c, {a, "b"}, {c, 10}]} = get_term(P),
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index 6d5c341eae..cad2686018 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -25,6 +25,7 @@
-include("ei_print_SUITE_data/ei_print_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, tuples/1, lists/1, strings/1]).
-import(runner, [get_term/1]).
@@ -38,10 +39,13 @@ suite() ->
all() ->
[atoms, tuples, lists, strings].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, "''"} = get_term(P),
{term, "a"} = get_term(P),
@@ -79,7 +83,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, "{}"} = get_term(P),
{term, "{a}"} = get_term(P),
@@ -100,7 +104,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, "[]"} = get_term(P),
{term, "[a]"} = get_term(P),
@@ -125,7 +129,7 @@ lists(Config) when is_list(Config) ->
ok.
strings(Config) when is_list(Config) ->
- P = runner:start(?strings),
+ P = runner:start(Config, ?strings),
{term, "\"\\n\""} = get_term(P),
{term, "\"\\r\\n\""} = get_term(P),
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 003fe20594..1e76a99e1e 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -39,14 +39,16 @@ all() ->
[framework_check, ei_accept_tmo, ei_connect_tmo,
ei_send_tmo, ei_recv_tmo].
-init_per_testcase(_Case, Config) ->
+init_per_testcase(Case, Config) ->
+ Config1 = runner:init_per_testcase(?MODULE, Case, Config),
+
% test if platform is vxworks_simso
{_,Host} = split(node()),
Bool = case atom_to_list(Host) of
[$v,$x,$s,$i,$m | _] -> true;
_ -> false
end,
- [{vxsim,Bool}|Config].
+ [{vxsim,Bool} | Config1].
end_per_testcase(_Case, _Config) ->
ok.
@@ -55,7 +57,7 @@ end_per_testcase(_Case, _Config) ->
framework_check(Config) when is_list(Config) ->
%%dbg:tracer(),
%%dbg:p(self()),
- P = runner:start(?framework_check),
+ P = runner:start(Config, ?framework_check),
runner:send_term(P,{hello,world}),
{term, {hello,world}} = runner:get_term(P),
runner:recv_eot(P),
@@ -71,7 +73,7 @@ ei_recv_tmo(Config) when is_list(Config) ->
do_one_recv(Config,CNode) ->
{_,Host} = split(node()),
- P1 = runner:start(?recv_tmo),
+ P1 = runner:start(Config, ?recv_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -84,7 +86,7 @@ do_one_recv(Config,CNode) ->
runner:recv_eot(P1).
do_one_recv_failure(Config,CNode) ->
- P1 = runner:start(?recv_tmo),
+ P1 = runner:start(Config, ?recv_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -110,7 +112,7 @@ ei_send_tmo(Config) when is_list(Config) ->
do_one_send(Config,From,CNode) ->
{_,Host} = split(node()),
- P1 = runner:start(?send_tmo),
+ P1 = runner:start(Config, ?send_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -139,7 +141,7 @@ do_one_send_failure(Config,From,FakeName,CName,VxSim) ->
exit(Else)
end,
EpmdSocket = register(OurName, LSocket, 1, 5),
- P3 = runner:start(?send_tmo),
+ P3 = runner:start(Config, ?send_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{CName,
Cookie,
@@ -202,7 +204,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
%dbg:p(self()),
VxSim = proplists:get_value(vxsim, Config),
DummyNode = make_and_check_dummy(),
- P = runner:start(?connect_tmo),
+ P = runner:start(Config, ?connect_tmo),
runner:send_term(P,{c_nod_connect_tmo_1,
kaksmula_som_ingen_bryr_sig_om,
DummyNode}),
@@ -219,7 +221,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
end
end,
runner:recv_eot(P),
- P2 = runner:start(?connect_tmo),
+ P2 = runner:start(Config, ?connect_tmo),
runner:send_term(P2,{c_nod_connect_tmo_2,
erlang:get_cookie(),
node()}),
@@ -237,7 +239,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
exit(Else)
end,
EpmdSocket = register(OurName, LSocket, 1, 5),
- P3 = runner:start(?connect_tmo),
+ P3 = runner:start(Config, ?connect_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{c_nod_connect_tmo_3,
Cookie,
@@ -266,12 +268,12 @@ ei_connect_tmo(Config) when is_list(Config) ->
ei_accept_tmo(Config) when is_list(Config) ->
%%dbg:tracer(),
%%dbg:p(self()),
- P = runner:start(?accept_tmo),
+ P = runner:start(Config, ?accept_tmo),
runner:send_term(P,{c_nod_som_ingen_kontaktar_1,
kaksmula_som_ingen_bryr_sig_om}),
{term,{-1,ETimedout,ETimedout}} = runner:get_term(P, 10000),
runner:recv_eot(P),
- P2 = runner:start(?accept_tmo),
+ P2 = runner:start(Config, ?accept_tmo),
runner:send_term(P2,{c_nod_som_vi_kontaktar_1,
erlang:get_cookie()}),
receive after 1000 -> ok end,
@@ -280,7 +282,7 @@ ei_accept_tmo(Config) when is_list(Config) ->
{term, X} = runner:get_term(P2, 10000),
runner:recv_eot(P2),
true = is_integer(X),
- P3 = runner:start(?accept_tmo),
+ P3 = runner:start(Config, ?accept_tmo),
runner:send_term(P3,{c_nod_som_vi_kontaktar_2,
erlang:get_cookie()}),
receive after 1000 -> ok end,
diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl
index cd73f07b8f..ad4e34c548 100644
--- a/lib/erl_interface/test/erl_connect_SUITE.erl
+++ b/lib/erl_interface/test/erl_connect_SUITE.erl
@@ -25,6 +25,7 @@
-include("erl_connect_SUITE_data/erl_connect_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
erl_send/1, erl_reg_send/1,
erl_send_cookie_file/1]).
@@ -38,8 +39,11 @@ all() ->
[erl_send, erl_reg_send, erl_send_cookie_file].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
erl_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = erl_connect(P, node()),
@@ -56,7 +60,7 @@ erl_send_cookie_file(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, '', 0),
{ok,Fd} = erl_connect(P, node()),
@@ -70,7 +74,7 @@ erl_send_cookie_file(Config) when is_list(Config) ->
end.
erl_reg_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = erl_connect(P, node()),
diff --git a/lib/erl_interface/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl
index 3d1e33081b..84b58fed54 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE.erl
+++ b/lib/erl_interface/test/erl_eterm_SUITE.erl
@@ -35,6 +35,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([all/0, suite/0,
+ init_per_testcase/2,
build_terms/1, round_trip_conversion/1,
decode_terms/1, decode_float/1,
t_erl_mk_int/1, t_erl_mk_list/1,
@@ -94,6 +95,9 @@ all() ->
high_chaparal, broken_data, cnode_1].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% 1. B a s i c t e s t s
@@ -104,7 +108,7 @@ all() ->
%% a list and verifies that the result is as expected.
build_terms(Config) when is_list(Config) ->
- P = runner:start(?build_terms),
+ P = runner:start(Config, ?build_terms),
{term, Term} = get_term(P),
io:format("Received: ~p", [Term]),
[ARefLN, ARef, APortLN, APort, APidLN, APid,
@@ -136,7 +140,7 @@ build_terms(Config) when is_list(Config) ->
%% This test is run entirely in C code.
round_trip_conversion(Config) when is_list(Config) ->
- runner:test(?round_trip_conversion),
+ runner:test(Config, ?round_trip_conversion),
ok.
%% This test sends a list of all data types to the C code function,
@@ -156,7 +160,7 @@ decode_terms(Config) when is_list(Config) ->
{element1, 42, 767}, "A string",
1, -1, 0, 3.0, ABinary, 'I am an atom'],
- P = runner:start(?decode_terms),
+ P = runner:start(Config, ?decode_terms),
runner:send_term(P, Terms),
runner:recv_eot(P),
@@ -165,7 +169,7 @@ decode_terms(Config) when is_list(Config) ->
%% Decodes the floating point number 3.1415.
decode_float(Config) when is_list(Config) ->
- P = runner:start(?decode_float),
+ P = runner:start(Config, ?decode_float),
runner:send_term(P, 3.1415),
runner:recv_eot(P),
ok.
@@ -173,7 +177,7 @@ decode_float(Config) when is_list(Config) ->
%% Tests the erl_free_compound() function.
t_erl_free_compound(Config) when is_list(Config) ->
- runner:test(?t_erl_free_compound),
+ runner:test(Config, ?t_erl_free_compound),
ok.
@@ -186,7 +190,7 @@ t_erl_free_compound(Config) when is_list(Config) ->
%% This tests the erl_mk_list() function.
t_erl_mk_list(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_list),
+ P = runner:start(Config, ?t_erl_mk_list),
{term, []} = get_term(P),
{term, [abc]} = get_term(P),
@@ -200,7 +204,7 @@ t_erl_mk_list(Config) when is_list(Config) ->
%% This tests the erl_mk_int() function.
t_erl_mk_int(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_int),
+ P = runner:start(Config, ?t_erl_mk_int),
{term, 0} = get_term(P),
{term, 127} = get_term(P),
@@ -255,14 +259,14 @@ t_erl_mk_int(Config) when is_list(Config) ->
%% Basic test of erl_copy_term().
basic_copy(Config) when is_list(Config) ->
- runner:test(?basic_copy),
+ runner:test(Config, ?basic_copy),
ok.
%% This tests the erl_mk_tuple() function.
t_erl_mk_tuple(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_tuple),
+ P = runner:start(Config, ?t_erl_mk_tuple),
{term, {madonna, 21, 'mad donna', 12}} = get_term(P),
{term, {'Madonna',21,{children,{"Isabella",2}},
@@ -275,7 +279,7 @@ t_erl_mk_tuple(Config) when is_list(Config) ->
%% This tests the erl_mk_atom() function.
t_erl_mk_atom(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_atom),
+ P = runner:start(Config, ?t_erl_mk_atom),
{term, madonna} = (get_term(P)),
{term, 'Madonna'} = (get_term(P)),
@@ -295,7 +299,7 @@ t_erl_mk_atom(Config) when is_list(Config) ->
%% This tests the erl_mk_binary() function.
t_erl_mk_binary(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_binary),
+ P = runner:start(Config, ?t_erl_mk_binary),
{term, Bin} = (get_term(P)),
"{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}" = binary_to_list(Bin),
@@ -307,7 +311,7 @@ t_erl_mk_binary(Config) when is_list(Config) ->
%% This tests the erl_mk_empty_list() function.
t_erl_mk_empty_list(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_empty_list),
+ P = runner:start(Config, ?t_erl_mk_empty_list),
{term, []} = get_term(P),
@@ -322,7 +326,7 @@ t_erl_mk_float(Config) when is_list(Config) ->
vxworks ->
{skipped, "Floating point numbers never compare equal on PPC"};
_ ->
- P = runner:start(?t_erl_mk_float),
+ P = runner:start(Config, ?t_erl_mk_float),
{term, {3.1415, 1.999999, 2.000000, 2.000001,
2.000002, 12345.67890}} = get_term(P),
runner:recv_eot(P),
@@ -333,7 +337,7 @@ t_erl_mk_float(Config) when is_list(Config) ->
%% This tests the erl_mk_pid() function.
t_erl_mk_pid(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_pid),
+ P = runner:start(Config, ?t_erl_mk_pid),
{term, A_pid} = (get_term(P)),
{pid, kalle@localhost, 3, 2} = nc2vinfo(A_pid),
@@ -342,7 +346,7 @@ t_erl_mk_pid(Config) when is_list(Config) ->
ok.
t_erl_mk_xpid(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_xpid),
+ P = runner:start(Config, ?t_erl_mk_xpid),
{term, A_pid} = (get_term(P)),
{pid, kalle@localhost, 32767, 8191} = nc2vinfo(A_pid),
@@ -354,7 +358,7 @@ t_erl_mk_xpid(Config) when is_list(Config) ->
%% This tests the erl_mk_port() function.
t_erl_mk_port(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_port),
+ P = runner:start(Config, ?t_erl_mk_port),
{term, A_port} = (get_term(P)),
{port, kalle@localhost, 4} = nc2vinfo(A_port),
@@ -363,7 +367,7 @@ t_erl_mk_port(Config) when is_list(Config) ->
ok.
t_erl_mk_xport(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_xport),
+ P = runner:start(Config, ?t_erl_mk_xport),
{term, A_port} = (get_term(P)),
{port, kalle@localhost, 268435455} = nc2vinfo(A_port),
@@ -375,7 +379,7 @@ t_erl_mk_xport(Config) when is_list(Config) ->
%% This tests the erl_mk_ref() function.
t_erl_mk_ref(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_ref),
+ P = runner:start(Config, ?t_erl_mk_ref),
{term, A_ref} = (get_term(P)),
{ref, kalle@localhost, _Length, [6]} = nc2vinfo(A_ref),
@@ -384,7 +388,7 @@ t_erl_mk_ref(Config) when is_list(Config) ->
ok.
t_erl_mk_long_ref(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_long_ref),
+ P = runner:start(Config, ?t_erl_mk_long_ref),
{term, A_ref} = (get_term(P)),
{ref, kalle@localhost, _Length, [4294967295,4294967295,262143]}
@@ -397,7 +401,7 @@ t_erl_mk_long_ref(Config) when is_list(Config) ->
%% This tests the erl_mk_string() function.
t_erl_mk_string(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_string),
+ P = runner:start(Config, ?t_erl_mk_string),
{term, "madonna"} = (get_term(P)),
{term, "Madonna"} = (get_term(P)),
@@ -417,7 +421,7 @@ t_erl_mk_string(Config) when is_list(Config) ->
%% This tests the erl_mk_estring() function.
t_erl_mk_estring(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_estring),
+ P = runner:start(Config, ?t_erl_mk_estring),
{term, "madonna"} = (get_term(P)),
{term, "Madonna"} = (get_term(P)),
@@ -437,7 +441,7 @@ t_erl_mk_estring(Config) when is_list(Config) ->
%% This tests the erl_mk_uint() function.
t_erl_mk_uint(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_uint),
+ P = runner:start(Config, ?t_erl_mk_uint),
{term, 54321} = (get_term(P)),
{term, 2147483647} = (get_term(P)),
@@ -453,7 +457,7 @@ t_erl_mk_uint(Config) when is_list(Config) ->
%% This tests the erl_mk_var() function.
t_erl_mk_var(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_var),
+ P = runner:start(Config, ?t_erl_mk_var),
{term, 1} = (get_term(P)),
{term, 0} = (get_term(P)),
@@ -470,7 +474,7 @@ t_erl_mk_var(Config) when is_list(Config) ->
%% This tests the erl_cons() function.
t_erl_cons(Config) when is_list(Config) ->
- P = runner:start(?t_erl_cons),
+ P = runner:start(Config, ?t_erl_cons),
{term, [madonna, 21]} = get_term(P),
@@ -490,7 +494,7 @@ t_erl_cons(Config) when is_list(Config) ->
%% Tests the erl_length() function.
t_erl_length(Config) when is_list(Config) ->
- P = runner:start(?t_erl_length),
+ P = runner:start(Config, ?t_erl_length),
0 = erl_length(P, []),
1 = erl_length(P, [a]),
@@ -513,7 +517,7 @@ erl_length(Port, List) ->
%% Tests the erl_hd() function.
t_erl_hd(Config) when is_list(Config) ->
- P = runner:start(?t_erl_hd),
+ P = runner:start(Config, ?t_erl_hd),
'NULL' = erl_hd(P, 42),
'NULL' = erl_hd(P, abc),
@@ -537,7 +541,7 @@ erl_hd(Port, List) ->
%% Tests the erl_tail() function.
t_erl_tl(Config) when is_list(Config) ->
- P = runner:start(?t_erl_tl),
+ P = runner:start(Config, ?t_erl_tl),
'NULL' = erl_tl(P, 42),
'NULL' = erl_tl(P, abc),
@@ -561,20 +565,20 @@ erl_tl(Port, List) ->
%% Tests the type checking macros (done in the C program).
type_checks(Config) when is_list(Config) ->
- runner:test(?type_checks),
+ runner:test(Config, ?type_checks),
ok.
%% Tests the extractor macros (done in the C program).
extractor_macros(Config) when is_list(Config) ->
- runner:test(?extractor_macros),
+ runner:test(Config, ?extractor_macros),
ok.
%% This tests the erl_size() function.
t_erl_size(Config) when is_list(Config) ->
- P = runner:start(?t_erl_size),
+ P = runner:start(Config, ?t_erl_size),
{term, 0} = (get_term(P)),
{term, 4} = (get_term(P)),
@@ -589,7 +593,7 @@ t_erl_size(Config) when is_list(Config) ->
%% This tests the erl_var_content() function.
t_erl_var_content(Config) when is_list(Config) ->
- P = runner:start(?t_erl_var_content),
+ P = runner:start(Config, ?t_erl_var_content),
{term, 17} = (get_term(P)),
{term, "http://www.madonna.com"} = (get_term(P)),
@@ -604,7 +608,7 @@ t_erl_var_content(Config) when is_list(Config) ->
%% This tests the erl_element() function.
t_erl_element(Config) when is_list(Config) ->
- P = runner:start(?t_erl_element),
+ P = runner:start(Config, ?t_erl_element),
{term, madonna} = get_term(P),
{term, 21} = get_term(P),
@@ -630,7 +634,7 @@ t_erl_element(Config) when is_list(Config) ->
%% Tests the erl_iolist_length() function.
t_erl_iolist_length(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_length),
+ P = runner:start(Config, ?t_erl_iolist_length),
%% Flat lists.
@@ -697,7 +701,7 @@ erl_iolist_length(Port, List) ->
%% Tests the erl_iolist_to_binary() function.
t_erl_iolist_to_binary(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_to_binary),
+ P = runner:start(Config, ?t_erl_iolist_to_binary),
%% Flat lists.
@@ -768,7 +772,7 @@ iolist_to_list(Port, Term) ->
%% Tests the erl_iolist_to_string() function.
t_erl_iolist_to_string(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_to_string),
+ P = runner:start(Config, ?t_erl_iolist_to_string),
%% Flat lists.
@@ -947,14 +951,14 @@ collect_line1([C|Rest], Result) ->
%% Test case submitted by Per Lundgren, ERV.
high_chaparal(Config) when is_list(Config) ->
- P = runner:start(?high_chaparal),
+ P = runner:start(Config, ?high_chaparal),
{term, [hello, world]} = get_term(P),
runner:recv_eot(P),
ok.
%% OTP-7448
broken_data(Config) when is_list(Config) ->
- P = runner:start(?broken_data),
+ P = runner:start(Config, ?broken_data),
runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/erl_ext_SUITE.erl b/lib/erl_interface/test/erl_ext_SUITE.erl
index afaba1fd93..806339b122 100644
--- a/lib/erl_interface/test/erl_ext_SUITE.erl
+++ b/lib/erl_interface/test/erl_ext_SUITE.erl
@@ -25,6 +25,7 @@
-include("erl_ext_SUITE_data/ext_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
compare_tuple/1,
compare_list/1,
compare_string/1,
@@ -40,28 +41,30 @@ all() ->
[compare_tuple, compare_list, compare_string,
compare_list_string, compare_nc_ext].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
compare_tuple(Config) when is_list(Config) ->
- P = runner:start(?compare_tuple),
+ P = runner:start(Config, ?compare_tuple),
runner:recv_eot(P),
ok.
compare_list(Config) when is_list(Config) ->
- P = runner:start(?compare_list),
+ P = runner:start(Config, ?compare_list),
runner:recv_eot(P),
ok.
compare_string(Config) when is_list(Config) ->
- P = runner:start(?compare_string),
+ P = runner:start(Config, ?compare_string),
runner:recv_eot(P),
ok.
compare_list_string(Config) when is_list(Config) ->
- P = runner:start(?compare_list_string),
+ P = runner:start(Config, ?compare_list_string),
runner:recv_eot(P),
ok.
compare_nc_ext(Config) when is_list(Config) ->
- P = runner:start(?compare_nc_ext),
+ P = runner:start(Config, ?compare_nc_ext),
runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl
index c1a7d8377e..d984dcb08e 100644
--- a/lib/erl_interface/test/erl_format_SUITE.erl
+++ b/lib/erl_interface/test/erl_format_SUITE.erl
@@ -25,6 +25,7 @@
-include("erl_format_SUITE_data/format_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, tuples/1, lists/1]).
-import(runner, [get_term/1]).
@@ -38,10 +39,13 @@ suite() ->
all() ->
[atoms, tuples, lists].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, ''} = get_term(P),
{term, 'a'} = get_term(P),
@@ -79,7 +83,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, {}} = get_term(P),
{term, {a}} = get_term(P),
@@ -100,7 +104,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, []} = get_term(P),
{term, [a]} = get_term(P),
diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/erl_global_SUITE.erl
index ecc6753c7f..560afd58ba 100644
--- a/lib/erl_interface/test/erl_global_SUITE.erl
+++ b/lib/erl_interface/test/erl_global_SUITE.erl
@@ -25,6 +25,7 @@
-include("erl_global_SUITE_data/erl_global_test_cases.hrl").
-export([all/0,suite/0,
+ init_per_testcase/2,
erl_global_registration/1,
erl_global_whereis/1, erl_global_names/1]).
@@ -39,9 +40,11 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {seconds, 30}}].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
erl_global_registration(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
ok = erl_global_register(P, Fd, ?GLOBAL_NAME),
@@ -53,7 +56,7 @@ erl_global_registration(Config) when is_list(Config) ->
ok.
erl_global_whereis(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
Self = self(),
@@ -66,7 +69,7 @@ erl_global_whereis(Config) when is_list(Config) ->
ok.
erl_global_names(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
Self = self(),
diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl
index 5566714092..f1f6892ae0 100644
--- a/lib/erl_interface/test/erl_match_SUITE.erl
+++ b/lib/erl_interface/test/erl_match_SUITE.erl
@@ -25,6 +25,7 @@
-include("erl_match_SUITE_data/match_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, lists/1, tuples/1, references/1, pids/1, ports/1,
bind/1, integers/1, floats/1, binaries/1, strings/1]).
@@ -40,6 +41,8 @@ all() ->
[atoms, lists, tuples, references, pids, ports, bind,
integers, floats, binaries, strings].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
atoms(Config) when is_list(Config) ->
P = start_matcher(Config),
@@ -239,7 +242,7 @@ bind(Config) when is_list(Config) ->
ok.
start_bind(Config) ->
- runner:start(?erl_match_bind).
+ runner:start(Config, ?erl_match_bind).
bind_ok(Port, Bind, Term) ->
true = erl_bind(Port, Bind, Term).
@@ -258,7 +261,7 @@ erl_bind(Port, Pattern, Term) ->
start_matcher(Config) ->
- runner:start(?erl_match_server).
+ runner:start(Config, ?erl_match_server).
eq(Port, Pattern, Term) ->
true = erl_match(Port, Pattern, Term).
diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl
index fb10bd895f..d31b2372ab 100644
--- a/lib/erl_interface/test/port_call_SUITE.erl
+++ b/lib/erl_interface/test/port_call_SUITE.erl
@@ -32,7 +32,9 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([all/0, suite/0, basic/1]).
+-export([all/0, suite/0,
+ init_per_testcase/2,
+ basic/1]).
% Private exports
-include_lib("common_test/include/ct.hrl").
@@ -44,6 +46,8 @@ suite() ->
all() ->
[basic].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
basic(Config) when is_list(Config) ->
case os:type() of
diff --git a/lib/erl_interface/test/runner.erl b/lib/erl_interface/test/runner.erl
index 947e56c4e0..484890006e 100644
--- a/lib/erl_interface/test/runner.erl
+++ b/lib/erl_interface/test/runner.erl
@@ -21,8 +21,9 @@
%%
-module(runner).
--export([test/1, test/2,
- start/1, send_term/2, finish/1, send_eot/1, recv_eot/1,
+-export([test/2, test/3,
+ init_per_testcase/3,
+ start/2, send_term/2, finish/1, send_eot/1, recv_eot/1,
get_term/1, get_term/2]).
-define(default_timeout, 5000).
@@ -32,11 +33,11 @@
%% This function is useful for test cases written in C which requires
%% no further input, and only returns a result by calling report().
-test(Tc) ->
- test(Tc, ?default_timeout).
+test(Config, Tc) ->
+ test(Config, Tc, ?default_timeout).
-test(Tc, Timeout) ->
- Port = start(Tc),
+test(Config, Tc, Timeout) ->
+ Port = start(Config, Tc),
case get_term(Port, Timeout) of
eot ->
@@ -54,12 +55,51 @@ test(Tc, Timeout) ->
%%
%% Returns: {ok, Port}
-start({Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
- Port = open_port({spawn, Prog}, [{packet, 4}, exit_status]),
+start(Config, {Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
+ Port = open_port({spawn, prog_cmd(Config, Prog)},
+ [{packet, 4}, exit_status]),
Command = [Tc div 256, Tc rem 256],
Port ! {self(), {command, Command}},
Port.
+prog_cmd(Config, Prog) ->
+ case proplists:get_value(valgrind_cmd_fun, Config) of
+ undefined ->
+ Prog;
+ Fun when is_function(Fun) ->
+ Fun(Prog)
+ end.
+
+init_per_testcase(Suite, Case, Config) ->
+ case os:getenv("VALGRIND_LOG_DIR") of
+ false ->
+ Config;
+ LogDir ->
+ Valgrind = case os:find_executable("valgrind") of
+ false ->
+ ct:fail("VALGRIND_LOG_DIR set, "
+ "but no valgrind executable found");
+ VG -> VG
+ end,
+
+ LogFileOpt = case os:getenv("VALGRIND_LOG_XML") of
+ false ->
+ " --log-file=";
+ "yes" ->
+ " --xml=yes --xml-file="
+ end,
+ Fun = fun(Prog) ->
+ LogFile = io_lib:format("erl_interface-~w.~w-~s.log.%p",
+ [Suite, Case, filename:basename(Prog)]),
+ Valgrind
+ ++ LogFileOpt ++ filename:join(LogDir,LogFile)
+ ++ " " ++ os:getenv("VALGRIND_MISC_FLAGS","")
+ ++ " " ++ Prog
+ end,
+ [{valgrind_cmd_fun, Fun} | Config]
+ end.
+
+
%% Finishes a test case by send an 'eot' message to the C program
%% and waiting for an 'eot'.
%%
diff --git a/lib/et/doc/src/Makefile b/lib/et/doc/src/Makefile
index 4758559220..93e2f8eeee 100644
--- a/lib/et/doc/src/Makefile
+++ b/lib/et/doc/src/Makefile
@@ -85,6 +85,7 @@ clean clean_docs:
fi \
done
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/et/doc/src/et_collector.xml b/lib/et/doc/src/et_collector.xml
index 6a85b81ec2..ba24c121e0 100644
--- a/lib/et/doc/src/et_collector.xml
+++ b/lib/et/doc/src/et_collector.xml
@@ -46,7 +46,8 @@
<v>option() = {parent_pid, pid()} | {event_order, event_order()} | {dict_insert, {filter, collector}, collector_fun()} | {dict_insert, {filter, event_filter_name()}, event_filter_fun()} | {dict_insert, {subscriber, pid()}, dict_val()} | {dict_insert, dict_key(), dict_val()} | {dict_delete, dict_key()} | {trace_client, trace_client()} | {trace_global, boolean()} | {trace_pattern, trace_pattern()} | {trace_port, integer()} | {trace_max_queue, integer()}</v>
<v>event_order() = trace_ts | event_ts</v>
<v>trace_pattern() = {report_module(), extended_dbg_match_spec()} | undefined</v>
- <v>report_module() = atom() | undefined &lt;v>extended_dbg_match_spec()() = detail_level() | dbg_match_spec()</v>
+ <v>report_module() = atom() | undefined</v>
+ <v>extended_dbg_match_spec() = detail_level() | dbg_match_spec()</v>
<v>detail_level() = min | max | integer(X) when X =&lt; 0, X >= 100</v>
<v>trace_client() = {event_file, file_name()} | {dbg_trace_type(), dbg_trace_parameters()}</v>
<v>file_name() = string()</v>
@@ -221,7 +222,7 @@
<v>CollectorPid = pid()</v>
<v>RawPattern = {report_module(), extended_dbg_match_spec()}</v>
<v>report_module() = atom() | undefined</v>
- <v>extended_dbg_match_spec()() = detail_level() | dbg_match_spec()</v>
+ <v>extended_dbg_match_spec() = detail_level() | dbg_match_spec()</v>
<v>RawPattern = detail_level()</v>
<v>detail_level() = min | max | integer(X) when X =&lt; 0, X >= 100</v>
<v>TracePattern = {report_module(), dbg_match_spec_match_spec()}</v>
@@ -348,7 +349,8 @@
<v>done() = 0</v>
<v>forward() = infinity | integer(X) where X > 0</v>
<v>backward() = '-infinity' | integer(X) where X &lt; 0</v>
- <v>Fun = fun(Event, Acc) -> NewAcc &lt;v>Acc = NewAcc = term()</v>
+ <v>Fun = fun(Event, Acc) -> NewAcc</v>
+ <v>Acc = NewAcc = term()</v>
</type>
<desc>
<p>Iterate over the currently stored events.</p>
diff --git a/lib/et/doc/src/et_selector.xml b/lib/et/doc/src/et_selector.xml
index 441a4dd278..b819bbf0c6 100644
--- a/lib/et/doc/src/et_selector.xml
+++ b/lib/et/doc/src/et_selector.xml
@@ -90,7 +90,9 @@
<fsummary>Transforms trace data and makes an event record out of it</fsummary>
<type>
- <v>Mod = module_name() | undefined &lt;v>module_name() = atom() &lt;v>ValidTraceData = erlang_trace_data() | record(event)</v>
+ <v>Mod = module_name() | undefined</v>
+ <v>module_name() = atom()</v>
+ <v>ValidTraceData = erlang_trace_data() | record(event)</v>
<v>erlang_trace_data() = {trace, Pid, Label, Info} | {trace, Pid, Label, Info, Extra} | {trace_ts, Pid, Label, Info, ReportedTS} | {trace_ts, Pid, Label, Info, Extra, ReportedTS} | {seq_trace, Label, Info} | {seq_trace, Label, Info, ReportedTS} | {drop, NumberOfDroppedItems}</v>
</type>
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index ffe244324c..b432df8c62 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -509,7 +509,7 @@ get_global_pid() ->
%% CollectorPid = pid()
%% RawPattern = {report_module(), extended_dbg_match_spec()}
%% report_module() = atom() | undefined
-%% extended_dbg_match_spec()() = detail_level() | dbg_match_spec()
+%% extended_dbg_match_spec() = detail_level() | dbg_match_spec()
%% RawPattern = detail_level()
%% detail_level() = min | max | integer(X) when X =< 0, X >= 100
%% TracePattern = {report_module(), dbg_match_spec_match_spec()}
diff --git a/lib/eunit/doc/src/Makefile b/lib/eunit/doc/src/Makefile
index e91d947592..117542cb37 100644
--- a/lib/eunit/doc/src/Makefile
+++ b/lib/eunit/doc/src/Makefile
@@ -146,6 +146,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/ftp/doc/src/Makefile b/lib/ftp/doc/src/Makefile
index e96a9c032f..20fbbc73a9 100644
--- a/lib/ftp/doc/src/Makefile
+++ b/lib/ftp/doc/src/Makefile
@@ -103,6 +103,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/ftp/doc/src/ftp.xml b/lib/ftp/doc/src/ftp.xml
index 3dbd3ed403..34e3ff84b0 100644
--- a/lib/ftp/doc/src/ftp.xml
+++ b/lib/ftp/doc/src/ftp.xml
@@ -314,7 +314,7 @@
<fsummary>Transfers a binary into a remote file.</fsummary>
<type>
<v>Pid = pid()</v>
- <v>Bin = binary()()</v>
+ <v>Bin = binary()</v>
<v>RemoteFile = string()</v>
<v>Reason = restriction_reason()| shortage_reason() | common_reason()</v>
</type>
@@ -546,11 +546,12 @@
<v>start_option() = {verbose, verbose()} | {debug, debug()}</v>
<v>verbose() = boolean() (default is false)</v>
<v>debug() = disable | debug | trace (default is disable)</v>
- <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()}</v>
+ <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress() | {sock_ctrl, sock_opts()} | {sock_data_act, sock_opts()} | {sock_data_pass, sock_opts()} }</v>
<v>ipfamily() = inet | inet6 | inet6fb4 (default is inet)</v>
<v>port() = integer() > 0 (default is 21)</v>
<v>mode() = active | passive (default is passive)</v>
<v>tls_options() = [<seealso marker="ssl:ssl#type-ssloption">ssl:ssloption()</seealso>]</v>
+ <v>sock_opts() = [<seealso marker="kernel:gen_tcp#type-option">gen_tcp:option()</seealso> except for ipv6_v6only, active, packet, mode, packet_size and header</v>
<v>timeout() = integer() > 0 (default is 60000 milliseconds)</v>
<v>dtimeout() = integer() > 0 | infinity (default is infinity)</v>
<v>pogress() = ignore | {module(), function(), initial_data()} (default is ignore)</v>
@@ -573,6 +574,11 @@
is used for securing both the control connection and the data sessions.
</p>
+ <p>The options <c>sock_ctrl</c>, <c>sock_data_act</c> and <c>sock_data_pass</c> passes options down to
+ the underlying transport layer (tcp). The default value for <c>sock_ctrl</c> is <c>[]</c>. Both
+ <c>sock_data_act</c> and <c>sock_data_pass</c> uses the value of <c>sock_ctrl</c> as default value.
+ </p>
+
<p>A session opened in this way is closed using function
<seealso marker="#close">close</seealso>.</p>
@@ -730,7 +736,7 @@
<fsummary>Transfers a binary into a remote file.</fsummary>
<type>
<v>Pid = pid()</v>
- <v>Bin = binary()()</v>
+ <v>Bin = binary()</v>
<v>RemoteFile = string()</v>
<v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
</type>
diff --git a/lib/ftp/src/ftp.erl b/lib/ftp/src/ftp.erl
index 8790bfec13..40f6b53fa3 100644
--- a/lib/ftp/src/ftp.erl
+++ b/lib/ftp/src/ftp.erl
@@ -101,6 +101,9 @@
%% data needed further on.
caller = undefined, % term()
ipfamily, % inet | inet6 | inet6fb4
+ sockopts_ctrl = [],
+ sockopts_data_passive = [],
+ sockopts_data_active = [],
progress = ignore, % ignore | pid()
dtimeout = ?DATA_ACCEPT_TIMEOUT, % non_neg_integer() | infinity
tls_upgrading_data_connection = false,
@@ -135,9 +138,10 @@ start_standalone(Options) ->
try
{ok, StartOptions} = start_options(Options),
{ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
case start_link(StartOptions, []) of
{ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
Error1 ->
Error1
end
@@ -149,10 +153,11 @@ start_standalone(Options) ->
start_service(Options) ->
try
{ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
{ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
Error1 ->
Error1
end
@@ -200,9 +205,10 @@ open({option_list, Options}) when is_list(Options) ->
try
{ok, StartOptions} = start_options(Options),
{ok, OpenOptions} = open_options(Options),
+ {ok, SockOpts} = socket_options(Options),
case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
{ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
+ call(Pid, {open, ip_comm, OpenOptions, SockOpts}, plain);
Error1 ->
Error1
end
@@ -227,9 +233,10 @@ open(Host, Opts) when is_list(Opts) ->
try
{ok, StartOptions} = start_options(Opts),
{ok, OpenOptions} = open_options([{host, Host}|Opts]),
+ {ok, SocketOptions} = socket_options(Opts),
case start_link(StartOptions, []) of
{ok, Pid} ->
- do_open(Pid, OpenOptions, tls_options(Opts));
+ do_open(Pid, OpenOptions, SocketOptions, tls_options(Opts));
Error1 ->
Error1
end
@@ -238,8 +245,8 @@ open(Host, Opts) when is_list(Opts) ->
Error2
end.
-do_open(Pid, OpenOptions, TLSOpts) ->
- case call(Pid, {open, ip_comm, OpenOptions}, plain) of
+do_open(Pid, OpenOptions, SocketOptions, TLSOpts) ->
+ case call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain) of
{ok, Pid} ->
maybe_tls_upgrade(Pid, TLSOpts);
Error ->
@@ -1026,7 +1033,7 @@ handle_call({_,latest_ctrl_response}, _, #state{latest_ctrl_response=Resp} = Sta
handle_call({Pid, _}, _, #state{owner = Owner} = State) when Owner =/= Pid ->
{reply, {error, not_connection_owner}, State};
-handle_call({_, {open, ip_comm, Opts}}, From, State) ->
+handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, From, State) ->
case key_search(host, Opts, undefined) of
undefined ->
{stop, normal, {error, ehost}, State};
@@ -1043,6 +1050,9 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
mode = Mode,
progress = progress(Progress),
ipfamily = IpFamily,
+ sockopts_ctrl = CtrlOpts,
+ sockopts_data_passive = DataPassOpts,
+ sockopts_data_active = DataActOpts,
dtimeout = DTimeout,
ftp_extension = FtpExt},
@@ -1055,28 +1065,6 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) ->
end
end;
-handle_call({_, {open, ip_comm, Host, Opts}}, From, State) ->
- Mode = key_search(mode, Opts, ?DEFAULT_MODE),
- Port = key_search(port, Opts, ?FTP_PORT),
- Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
- DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
- Progress = key_search(progress, Opts, ignore),
- FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
-
- State2 = State#state{client = From,
- mode = Mode,
- progress = progress(Progress),
- dtimeout = DTimeout,
- ftp_extension = FtpExt},
-
- case setup_ctrl_connection(Host, Port, Timeout, State2) of
- {ok, State3, WaitTimeout} ->
- {noreply, State3, WaitTimeout};
- {error, _Reason} ->
- gen_server:reply(From, {error, ehost}),
- {stop, normal, State2#state{client = undefined}}
- end;
-
handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State) ->
_ = send_ctrl_message(State, mk_cmd("AUTH TLS", [])),
activate_ctrl_connection(State),
@@ -1659,11 +1647,12 @@ handle_ctrl_result({pos_compl, Lines},
client = From,
caller = {setup_data_connection, Caller},
csock = CSock,
+ sockopts_data_passive = SockOpts,
timeout = Timeout}
= State) ->
[_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
{ok, {IP, _}} = peername(CSock),
- case connect(IP, list_to_integer(PortStr), Timeout, State) of
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
{ok, _, Socket} ->
handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
{error, _Reason} = Error ->
@@ -1676,7 +1665,8 @@ handle_ctrl_result({pos_compl, Lines},
ipfamily = inet,
client = From,
caller = {setup_data_connection, Caller},
- timeout = Timeout,
+ timeout = Timeout,
+ sockopts_data_passive = SockOpts,
ftp_extension = false} = State) ->
{_, [?LEFT_PAREN | Rest]} =
@@ -1690,7 +1680,7 @@ handle_ctrl_result({pos_compl, Lines},
Port = (P1 * 256) + P2,
?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,Port,Caller]),
- case connect(IP, Port, Timeout, State) of
+ case connect(IP, Port, SockOpts, Timeout, State) of
{ok, _, Socket} ->
handle_caller(State#state{caller = Caller, dsock = {tcp,Socket}});
{error, _Reason} = Error ->
@@ -1705,13 +1695,14 @@ handle_ctrl_result({pos_compl, Lines},
caller = {setup_data_connection, Caller},
csock = CSock,
timeout = Timeout,
+ sockopts_data_passive = SockOpts,
ftp_extension = true} = State) ->
[_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
{ok, {IP, _}} = peername(CSock),
?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,PortStr,Caller]),
- case connect(IP, list_to_integer(PortStr), Timeout, State) of
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
{ok, _, Socket} ->
handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
{error, _Reason} = Error ->
@@ -2075,9 +2066,9 @@ handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
%% Connect to FTP server at Host (default is TCP port 21)
%% in order to establish a control connection.
-setup_ctrl_connection(Host, Port, Timeout, State) ->
+setup_ctrl_connection(Host, Port, Timeout, #state{sockopts_ctrl = SockOpts} = State) ->
MsTime = erlang:monotonic_time(),
- case connect(Host, Port, Timeout, State) of
+ case connect(Host, Port, SockOpts, Timeout, State) of
{ok, IpFam, CSock} ->
NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
activate_ctrl_connection(NewState),
@@ -2095,12 +2086,15 @@ setup_ctrl_connection(Host, Port, Timeout, State) ->
setup_data_connection(#state{mode = active,
caller = Caller,
csock = CSock,
+ sockopts_data_active = SockOpts,
ftp_extension = FtpExt} = State) ->
case (catch sockname(CSock)) of
- {ok, {{_, _, _, _, _, _, _, _} = IP, _}} ->
+ {ok, {{_, _, _, _, _, _, _, _} = IP0, _}} ->
+ IP = proplists:get_value(ip, SockOpts, IP0),
{ok, LSock} =
gen_tcp:listen(0, [{ip, IP}, {active, false},
- inet6, binary, {packet, 0}]),
+ inet6, binary, {packet, 0} |
+ lists:keydelete(ip,1,SockOpts)]),
{ok, {_, Port}} = sockname({tcp,LSock}),
IpAddress = inet_parse:ntoa(IP),
Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
@@ -2108,9 +2102,11 @@ setup_data_connection(#state{mode = active,
activate_ctrl_connection(State),
{noreply, State#state{caller = {setup_data_connection,
{LSock, Caller}}}};
- {ok, {{_,_,_,_} = IP, _}} ->
+ {ok, {{_,_,_,_} = IP0, _}} ->
+ IP = proplists:get_value(ip, SockOpts, IP0),
{ok, LSock} = gen_tcp:listen(0, [{ip, IP}, {active, false},
- binary, {packet, 0}]),
+ binary, {packet, 0} |
+ lists:keydelete(ip,1,SockOpts)]),
{ok, Port} = inet:port(LSock),
_ = case FtpExt of
false ->
@@ -2149,41 +2145,41 @@ setup_data_connection(#state{mode = passive, ipfamily = inet,
activate_ctrl_connection(State),
{noreply, State#state{caller = {setup_data_connection, Caller}}}.
-connect(Host, Port, Timeout, #state{ipfamily = inet = IpFam}) ->
- connect2(Host, Port, IpFam, Timeout);
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet = IpFam}) ->
+ connect2(Host, Port, IpFam, SockOpts, Timeout);
-connect(Host, Port, Timeout, #state{ipfamily = inet6 = IpFam}) ->
- connect2(Host, Port, IpFam, Timeout);
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6 = IpFam}) ->
+ connect2(Host, Port, IpFam, SockOpts, Timeout);
-connect(Host, Port, Timeout, #state{ipfamily = inet6fb4}) ->
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6fb4}) ->
case inet:getaddr(Host, inet6) of
{ok, {0, 0, 0, 0, 0, 16#ffff, _, _} = IPv6} ->
case inet:getaddr(Host, inet) of
{ok, IPv4} ->
IpFam = inet,
- connect2(IPv4, Port, IpFam, Timeout);
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
_ ->
IpFam = inet6,
- connect2(IPv6, Port, IpFam, Timeout)
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout)
end;
{ok, IPv6} ->
IpFam = inet6,
- connect2(IPv6, Port, IpFam, Timeout);
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout);
_ ->
case inet:getaddr(Host, inet) of
{ok, IPv4} ->
IpFam = inet,
- connect2(IPv4, Port, IpFam, Timeout);
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
Error ->
Error
end
end.
-connect2(Host, Port, IpFam, Timeout) ->
- Opts = [IpFam, binary, {packet, 0}, {active, false}],
+connect2(Host, Port, IpFam, SockOpts, Timeout) ->
+ Opts = [IpFam, binary, {packet, 0}, {active, false} | SockOpts],
case gen_tcp:connect(Host, Port, Opts, Timeout) of
{ok, Sock} ->
{ok, IpFam, Sock};
@@ -2553,6 +2549,32 @@ open_options(Options) ->
{ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
validate_options(Options, ValidOptions, []).
+socket_options(Options) ->
+ CtrlOpts = proplists:get_value(sock_ctrl, Options, []),
+ DataActOpts = proplists:get_value(sock_data_act, Options, CtrlOpts),
+ DataPassOpts = proplists:get_value(sock_data_pass, Options, CtrlOpts),
+ case [O || O <- lists:usort(CtrlOpts++DataPassOpts++DataActOpts),
+ not valid_socket_option(O)] of
+ [] ->
+ {ok, {CtrlOpts, DataPassOpts, DataActOpts}};
+ Invalid ->
+ throw({error,{sock_opts,Invalid}})
+ end.
+
+
+valid_socket_option(inet ) -> false;
+valid_socket_option(inet6 ) -> false;
+valid_socket_option({ipv6_v6only, _}) -> false;
+valid_socket_option({active,_} ) -> false;
+valid_socket_option({packet,_} ) -> false;
+valid_socket_option({mode,_} ) -> false;
+valid_socket_option(binary ) -> false;
+valid_socket_option(list ) -> false;
+valid_socket_option({header,_} ) -> false;
+valid_socket_option({packet_size,_} ) -> false;
+valid_socket_option(_) -> true.
+
+
tls_options(Options) ->
%% Options will be validated by ssl application
proplists:get_value(tls, Options, undefined).
diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile
index 1c774d3357..bd6a7b2f74 100644
--- a/lib/hipe/doc/src/Makefile
+++ b/lib/hipe/doc/src/Makefile
@@ -94,6 +94,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml
index 63bc6ea2d7..99759a2f2c 100644
--- a/lib/hipe/doc/src/hipe_app.xml
+++ b/lib/hipe/doc/src/hipe_app.xml
@@ -78,12 +78,12 @@
</item>
<tag>NIFs</tag>
- <item><p>Modules compiled with HiPE can not call <seealso marker="erts:erlang#load_nif-2">
+ <item><p>Modules compiled with HiPE cannot call <seealso marker="erts:erlang#load_nif-2">
<c>erlang:load_nif/2</c></seealso> to load NIFs.</p>
</item>
<tag>-on_load</tag>
- <item><p>Modules compiled with HiPE can not use
+ <item><p>Modules compiled with HiPE cannot use
<seealso marker="doc/reference_manual:code_loading#on_load"><c>-on_load()</c></seealso>
directives.</p>
</item>
diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index 34b18acccd..098a7a8d8c 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -1633,7 +1633,7 @@ inf_bsl(_, pos_inf) -> neg_inf;
inf_bsl(Number, neg_inf) when is_integer(Number), Number >= 0 -> 0;
inf_bsl(_Number, neg_inf) -> -1;
inf_bsl(Number1, Number2) when is_integer(Number1), is_integer(Number2) ->
- %% We can not shift left with a number which is not a fixnum. We
+ %% We cannot shift left with a number which is not a fixnum. We
%% don't have enough memory.
Bits = ?BITS,
if Number2 > (Bits bsl 1) -> inf_bsl(Number1, pos_inf);
diff --git a/lib/hipe/rtl/hipe_icode2rtl.erl b/lib/hipe/rtl/hipe_icode2rtl.erl
index 6da8a76d34..1ab41f4deb 100644
--- a/lib/hipe/rtl/hipe_icode2rtl.erl
+++ b/lib/hipe/rtl/hipe_icode2rtl.erl
@@ -215,7 +215,7 @@ gen_enter(I, VarMap, ConstTab) ->
{Code1, ConstTab2} =
case hipe_icode:enter_type(I) of
primop ->
- IsGuard = false, % enter can not happen in a guard
+ IsGuard = false, % enter cannot happen in a guard
hipe_rtl_primops:gen_enter_primop({Fun, Args}, IsGuard, ConstTab1);
Type ->
Call = gen_enter_1(Fun, Args, Type),
diff --git a/lib/hipe/rtl/hipe_rtl_arith.inc b/lib/hipe/rtl/hipe_rtl_arith.inc
index c05b7aa160..575f10b542 100644
--- a/lib/hipe/rtl/hipe_rtl_arith.inc
+++ b/lib/hipe/rtl/hipe_rtl_arith.inc
@@ -118,8 +118,8 @@ eval_alu(Op, Arg1, Arg2) ->
%% Björn & Bjarni:
%% We need to be able to do evaluations based only on the bits, since
-%% there are cases where we can evaluate a subset of the bits, but can
-%% not do a full eval-alub call (eg. a + 0 gives no carry)
+%% there are cases where we can evaluate a subset of the bits, but
+%% cannot do a full eval-alub call (eg. a + 0 gives no carry)
%%
-spec eval_cond_bits(hipe_rtl:alub_cond(), boolean(),
boolean(), boolean(), boolean()) -> boolean().
diff --git a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
index cad43e2df5..72373e536d 100644
--- a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
+++ b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl
@@ -31,11 +31,11 @@
%%
%% Some things to note:
%%
-%% 1. All precoloured registers are assumed to contain bottom. We can not
+%% 1. All precoloured registers are assumed to contain bottom. We cannot
%% do anything with them since they are not in SSA-form. This might be
%% possible to resolve in some way, but we decided to not go there.
%%
-%% 2. const_labels are assumed to be bottom, we can not find the address
+%% 2. const_labels are assumed to be bottom, we cannot find the address
%% in any nice way (that I know of, maybe someone can help ?). I
%% suppose they don't get a value until linking (or some step that
%% resembles it). They are only affecting bignums and floats (at least
@@ -579,7 +579,7 @@ visit_multimove(Inst, Env) ->
%% Procedure : visit_call/2
%% Purpose : execute a call-instruction. All calls return bottom. We make
%% this assumption since the icode-leel have taken care of BIF's
-%% and we belive that we are left with the things that can not be
+%% and we belive that we are left with the things that cannot be
%% done att compile time.
%% Arguments : Inst - The instruction
%% Env - The environment
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index 29b8678cda..cbc0e384d8 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -115,6 +115,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 2c70c2b050..e5adb4eb20 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -173,7 +173,7 @@
<item>
<p>For <c>ip_comm</c> configuration options, see
<seealso marker="kernel:gen_tcp#listen-2">gen_tcp:listen/2</seealso>, some options
- that are used internally by httpd can not be set.</p>
+ that are used internally by httpd cannot be set.</p>
<p>For <c>SSL</c> configuration options, see
<seealso marker="ssl:ssl#listen-2">ssl:listen/2</seealso>.</p>
<p>Default is <c>ip_comm</c>.</p>
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index ec8d6ec42c..d65d2ff998 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -135,7 +135,8 @@
<type>
<v>What = atom()</v>
<v>Port = integer()</v>
- <v>Address = {A,B,C,D} | string() &lt;v>Dir = string()</v>
+ <v>Address = {A,B,C,D} | string()</v>
+ <v>Dir = string()</v>
<v>Data = [Info]</v>
<v>Info = {Name, Value}</v>
</type>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index f4bf4b1e1f..88a4335f60 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,7 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 7.0</title>
+ <section><title>Inets 7.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -79,7 +79,6 @@
</list>
</section>
-
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -91,8 +90,58 @@
</list>
</section>
+ </section>
+
+ <section><title>Inets 6.5.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
</section>
+<section><title>Inets 6.5.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Inets 6.5.2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Options added for setting low-level properties on the
+ underlying TCP connections. The options are:
+ <c>sock_ctrl</c>, <c>sock_data_act</c> and
+ <c>sock_data_pass</c>. See the manual for details.</p>
+ <p>
+ Own Id: OTP-15120 Aux Id: ERIERL-192 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
<section><title>Inets 6.5.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1149,7 +1198,7 @@
Add option {ftp_extension, boolean} to enable use of
extended commands EPSV and EPRT, as specified in RFC
2428, for IPv4 instead of using the legacy commands. Ipv6
- can not be supported without the extended commands.</p>
+ cannot be supported without the extended commands.</p>
<p>
Own Id: OTP-12255</p>
</item>
diff --git a/lib/inets/doc/src/notes_history.xml b/lib/inets/doc/src/notes_history.xml
index c12899e614..1523827db9 100644
--- a/lib/inets/doc/src/notes_history.xml
+++ b/lib/inets/doc/src/notes_history.xml
@@ -1149,8 +1149,8 @@
<list type="bulleted">
<item>
<p>When further testing the functionality of https requests
- that goes through a proxy. We realised that alas this can
- not currently be supported as it requires features from
+ that goes through a proxy. We realised that alas this
+ cannot currently be supported as it requires features from
the ssl implementation that is not currently available.
So for now an error message will be returned when trying
to use this functionality.</p>
diff --git a/lib/inets/src/http_client/httpc_cookie.erl b/lib/inets/src/http_client/httpc_cookie.erl
index cbf428ab3e..2e647a1438 100644
--- a/lib/inets/src/http_client/httpc_cookie.erl
+++ b/lib/inets/src/http_client/httpc_cookie.erl
@@ -271,7 +271,7 @@ lookup_cookies(CookieDb, Host, Path) ->
lookup_domain_cookies(_CookieDb, [], AccCookies) ->
lists:flatten(AccCookies);
-%% Top domains can not have cookies
+%% Top domains cannot have cookies
lookup_domain_cookies(_CookieDb, [_], AccCookies) ->
lists:flatten(AccCookies);
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 0f3bd0a06d..bb6b76da89 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -398,7 +398,7 @@ redirect(Response = {_, Headers, _}, Request) ->
THost = http_util:maybe_add_brackets(maps:get(host, URIMap), Brackets),
TPort = maps:get(port, URIMap),
TPath = maps:get(path, URIMap),
- TQuery = maps:get(query, URIMap, ""),
+ TQuery = add_question_mark(maps:get(query, URIMap, "")),
NewURI = uri_string:normalize(
uri_string:recompose(URIMap)),
HostPort = http_request:normalize_host(TScheme, THost, TPort),
@@ -417,29 +417,38 @@ redirect(Response = {_, Headers, _}, Request) ->
end
end.
+add_question_mark(<<>>) ->
+ <<>>;
+add_question_mark([]) ->
+ [];
+add_question_mark(Comp) when is_binary(Comp) ->
+ <<$?, Comp/binary>>;
+add_question_mark(Comp) when is_list(Comp) ->
+ [$?|Comp].
%% RFC3986 - 5.2.2. Transform References
resolve_uri(Scheme, Host, Port, Path, Query, URI) ->
resolve_uri(Scheme, Host, Port, Path, Query, URI, #{}).
%%
resolve_uri(Scheme, Host, Port, Path, Query, URI, Map0) ->
- case maps:is_key(scheme, URI) of
- true ->
- Port = get_port(URI),
+ case maps:get(scheme, URI, undefined) of
+ undefined ->
+ Port0 = get_port(Scheme, URI),
+ Map = Map0#{scheme => Scheme,
+ port => Port0},
+ resolve_authority(Host, Port, Path, Query, URI, Map);
+ URIScheme ->
+ Port0 = get_port(URIScheme, URI),
maybe_add_query(
- Map0#{scheme => maps:get(scheme, URI),
- host => maps:get(host, URI),
- port => Port,
- path => maps:get(path, URI)},
- URI);
- false ->
- Map = Map0#{scheme => Scheme},
- resolve_authority(Host, Port, Path, Query, URI, Map)
+ Map0#{scheme => URIScheme,
+ host => maps:get(host, URI),
+ port => Port0,
+ path => maps:get(path, URI)},
+ URI)
end.
-get_port(URI) ->
- Scheme = maps:get(scheme, URI),
+get_port(Scheme, URI) ->
case maps:get(port, URI, undefined) of
undefined ->
get_default_port(Scheme);
@@ -457,15 +466,13 @@ get_default_port("https") ->
resolve_authority(Host, Port, Path, Query, RelURI, Map) ->
case maps:is_key(host, RelURI) of
true ->
- Port = get_port(RelURI),
maybe_add_query(
Map#{host => maps:get(host, RelURI),
- port => Port,
path => maps:get(path, RelURI)},
RelURI);
false ->
Map1 = Map#{host => Host,
- port => Port},
+ port => Port},
resolve_path(Path, Query, RelURI, Map1)
end.
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 4d419172d0..fb71834e95 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -33,6 +33,9 @@ handle_error(enoent, Op, ModData, Path) ->
handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
": A component of the file name is not a directory");
+handle_error(eisdir, Op, ModData, Path) ->
+ handle_error(403, Op, ModData, Path,
+ ":Ilegal operation expected a file not a directory");
handle_error(emfile, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 3ee8665a54..bb946664f9 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -61,8 +61,12 @@ generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
{StatusCode, Response} -> %% Old way
send_response_old(ModData, StatusCode, Response),
ok;
- undefined ->
- send_status(ModData, 500, none),
+ undefined ->
+ %% Happens when no mod_*
+ %% handles the request
+ send_status(ModData, 501, {ModData#mod.method,
+ ModData#mod.request_uri,
+ ModData#mod.http_version}),
ok
end
end
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index d6b0e5f9f5..0a5aed67d5 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -435,7 +435,7 @@ http_request(Config) when is_list(Config) ->
[<<>>, Length1], HttpBody1)).
%%-------------------------------------------------------------------------
validate_request_line() ->
- [{doc, "Test httpd_request:validate/3. Makes sure you can not get past"
+ [{doc, "Test httpd_request:validate/3. Makes sure you cannot get past"
" the server_root and that the request is recognized by the server"
" and protcol version."}].
validate_request_line(Config) when is_list(Config) ->
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index d43e2cc179..6e048a4d56 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -59,7 +59,8 @@ all() ->
{group, http_unix_socket},
{group, https},
{group, sim_https},
- {group, misc}
+ {group, misc},
+ {group, sim_mixed} % HTTP and HTTPS sim servers
].
groups() ->
@@ -74,7 +75,8 @@ groups() ->
{http_unix_socket, [], simulated_unix_socket()},
{https, [], real_requests()},
{sim_https, [], only_simulated()},
- {misc, [], misc()}
+ {misc, [], misc()},
+ {sim_mixed, [], sim_mixed()}
].
real_requests()->
@@ -170,6 +172,12 @@ misc() ->
wait_for_whole_response
].
+sim_mixed() ->
+ [
+ redirect_http_to_https,
+ redirect_relative_different_port
+ ].
+
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -195,7 +203,8 @@ init_per_group(misc = Group, Config) ->
Config;
-init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https->
+init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https;
+ Group =:= sim_mixed ->
catch crypto:stop(),
try crypto:start() of
ok ->
@@ -238,6 +247,13 @@ end_per_group(http_unix_socket,_Config) ->
end_per_group(_, _Config) ->
ok.
+do_init_per_group(Group=sim_mixed, Config0) ->
+ % The mixed group uses two server ports (http and https), so we use
+ % different config names here.
+ Config1 = init_ssl(Config0),
+ Config2 = proplists:delete(http_port, proplists:delete(https_port, Config1)),
+ {HttpPort, HttpsPort} = server_start(Group, server_config(sim_https, Config2)),
+ [{http_port, HttpPort} | [{https_port, HttpsPort} | Config2]];
do_init_per_group(Group, Config0) ->
Config1 =
case Group of
@@ -734,6 +750,48 @@ redirect_loop(Config) when is_list(Config) ->
= httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
+redirect_http_to_https() ->
+ [{doc, "Test that a 30X redirect from one scheme to another is handled "
+ "correctly."}].
+redirect_http_to_https(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+ TargetUrl = mixed_url(https, "/dummy.html", Config),
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
+redirect_relative_different_port() ->
+ [{doc, "Test that a 30X redirect with a relative target, but different "
+ "port, is handled correctly."}].
+redirect_relative_different_port(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+
+ % We need an extra server of the same protocol here, so spawn a new
+ % HTTP-protocol one
+ Port = server_start(sim_http, []),
+ {ok, Host} = inet:gethostname(),
+ % Prefix the URI with '/' instead of a scheme
+ TargetUrl = "//" ++ Host ++ ":" ++ integer_to_list(Port) ++ "/dummy.html",
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
cookie() ->
[{doc, "Test cookies."}].
cookie(Config) when is_list(Config) ->
@@ -1559,6 +1617,21 @@ url(sim_http, UserInfo, End, Config) ->
url(sim_https, UserInfo, End, Config) ->
url(https, UserInfo, End, Config).
+% Only for use in the `mixed` test group, where both http and https
+% URLs are possible.
+mixed_url(http, End, Config) ->
+ mixed_url(http_port, End, Config);
+mixed_url(https, End, Config) ->
+ mixed_url(https_port, End, Config);
+mixed_url(PortType, End, Config) ->
+ Port = proplists:get_value(PortType, Config),
+ {ok, Host} = inet:gethostname(),
+ Start = case PortType of
+ http_port -> ?URL_START;
+ https_port -> ?TLS_URL_START
+ end,
+ Start ++ Host ++ ":" ++ integer_to_list(Port) ++ End.
+
group_name(Config) ->
GroupProp = proplists:get_value(tc_group_properties, Config),
proplists:get_value(name, GroupProp).
@@ -1587,6 +1660,9 @@ server_start(http_ipv6, HttpdConfig) ->
Serv = inets:services_info(),
{value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
proplists:get_value(port, Info);
+server_start(sim_mixed, Config) ->
+ % For the mixed http/https case, we start two servers and return both ports.
+ {server_start(sim_http, []), server_start(sim_https, Config)};
server_start(_, HttpdConfig) ->
{ok, Pid} = inets:start(httpd, HttpdConfig),
Serv = inets:services_info(),
@@ -1645,6 +1721,8 @@ start_apps(https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(sim_https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(sim_mixed) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(_) ->
ok.
@@ -2089,6 +2167,20 @@ handle_uri(_,"/301_rel_uri.html",_,_,_,_) ->
"Content-Length:" ++ integer_to_list(length(Body))
++ "\r\n\r\n" ++ Body;
+handle_uri("HEAD","/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
handle_uri("HEAD","/302.html",Port,_,Socket,_) ->
NewUri = url_start(Socket) ++
diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl
index 198b245399..3ee7981660 100644
--- a/lib/inets/test/httpc_proxy_SUITE.erl
+++ b/lib/inets/test/httpc_proxy_SUITE.erl
@@ -534,7 +534,7 @@ init_local_proxy(Config) ->
ct:fail({local_proxy_start_failed,Error})
end;
_ ->
- {skip,"Platform can not run local proxy start script"}
+ {skip,"Platform cannot run local proxy start script"}
end.
init_local_proxy_string(String, Config) ->
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 97aca73d6b..c5751e79a6 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -76,6 +76,8 @@ all() ->
{group, http_logging},
{group, http_post},
{group, http_rel_path_script_alias},
+ {group, http_not_sup},
+ {group, https_not_sup},
mime_types_format
].
@@ -103,6 +105,8 @@ groups() ->
{http_reload, [], [{group, reload}]},
{https_reload, [], [{group, reload}]},
{http_post, [], [{group, post}]},
+ {http_not_sup, [], [{group, not_sup}]},
+ {https_not_sup, [], [{group, not_sup}]},
{http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]},
{limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
{custom, [], [customize, add_default]},
@@ -134,7 +138,8 @@ groups() ->
esi_put, esi_post] ++ http_head() ++ http_get() ++ load()},
{http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()},
{http_0_9, [], http_head() ++ http_get() ++ load()},
- {http_rel_path_script_alias, [], [cgi]}
+ {http_rel_path_script_alias, [], [cgi]},
+ {not_sup, [], [put_not_sup]}
].
basic_groups ()->
@@ -207,7 +212,8 @@ init_per_group(Group, Config0) when Group == https_basic;
Group == https_auth_api_dets;
Group == https_auth_api_mnesia;
Group == https_security;
- Group == https_reload
+ Group == https_reload;
+ Group == https_not_sup
->
catch crypto:stop(),
try crypto:start() of
@@ -226,6 +232,7 @@ init_per_group(Group, Config0) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_security;
Group == http_reload;
+ Group == http_not_sup;
Group == http_post;
Group == http_mime_types
->
@@ -275,6 +282,8 @@ init_per_group(http_logging, Config) ->
init_per_group(http_rel_path_script_alias = Group, Config) ->
ok = start_apps(Group),
init_httpd(Group, [{type, ip_comm},{http_version, "HTTP/1.1"}| Config]);
+init_per_group(not_sup, Config) ->
+ [{http_version, "HTTP/1.1"} | Config];
init_per_group(_, Config) ->
Config.
@@ -448,8 +457,19 @@ get(Config) when is_list(Config) ->
{header, "Content-Type", "text/html"},
{header, "Date"},
{header, "Server"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
+ transport_opts(Type, Config),
+ proplists:get_value(node, Config),
+ http_request("GET /open/ ", Version, Host),
+ [{statuscode, 403},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
{version, Version}]).
-
+
basic_auth_1_1(Config) when is_list(Config) ->
basic_auth([{http_version, "HTTP/1.1"} | Config]).
@@ -898,6 +918,33 @@ max_clients_0_9() ->
max_clients_0_9(Config) when is_list(Config) ->
do_max_clients([{http_version, "HTTP/0.9"} | Config]).
+
+
+%%-------------------------------------------------------------------------
+put_not_sup() ->
+ [{doc, "Test unhandled request"}].
+
+put_not_sup(Config) when is_list(Config) ->
+ ok = http_status("PUT /index.html ",
+ {"Content-Length:100 \r\n",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"},
+ Config, [{statuscode, 501}]).
%%-------------------------------------------------------------------------
esi() ->
[{doc, "Test mod_esi"}].
@@ -1793,7 +1840,8 @@ start_apps(Group) when Group == https_basic;
Group == https_auth_api_mnesia;
Group == https_htaccess;
Group == https_security;
- Group == https_reload
+ Group == https_reload;
+ Group == https_not_sup
->
inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]);
start_apps(Group) when Group == http_basic;
@@ -1809,7 +1857,9 @@ start_apps(Group) when Group == http_basic;
Group == http_reload;
Group == http_post;
Group == http_mime_types;
- Group == http_rel_path_script_alias ->
+ Group == http_rel_path_script_alias;
+ Group == http_not_sup;
+ Group == http_mime_types->
inets_test_lib:start_apps([inets]).
server_start(_, HttpdConfig) ->
@@ -1844,6 +1894,10 @@ server_config(http_basic, Config) ->
basic_conf() ++ server_config(http, Config);
server_config(https_basic, Config) ->
basic_conf() ++ server_config(https, Config);
+server_config(http_not_sup, Config) ->
+ not_sup_conf() ++ server_config(http, Config);
+server_config(https_not_sup, Config) ->
+ not_sup_conf() ++ server_config(https, Config);
server_config(http_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(http, Config);
server_config(http_post, Config) ->
@@ -1992,7 +2046,9 @@ head_status(_) ->
basic_conf() ->
[{modules, [mod_alias, mod_range, mod_responsecontrol,
- mod_trace, mod_esi, mod_cgi, mod_dir, mod_get, mod_head]}].
+ mod_trace, mod_esi, mod_cgi, mod_get, mod_head]}].
+not_sup_conf() ->
+ [{modules, [mod_get]}].
auth_access_conf() ->
[{modules, [mod_alias, mod_htaccess, mod_dir, mod_get, mod_head]},
diff --git a/lib/jinterface/doc/src/Makefile b/lib/jinterface/doc/src/Makefile
index 37de0a35c5..6f1ecc8dea 100644
--- a/lib/jinterface/doc/src/Makefile
+++ b/lib/jinterface/doc/src/Makefile
@@ -129,6 +129,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index 9aaa8a0840..640712ad98 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -705,7 +705,7 @@
<item>
<p><c>OtpMbox.receive()</c> and <c>OtpMbox.receive(long timeout)</c> can now throw
<c>OtpErlangDecodeException</c> if the received message
- can not be decoded. <c>null</c> is now only returned from
+ cannot be decoded. <c>null</c> is now only returned from
<c>OtpMbox.receive(long timeout)</c> if a timeout occurs.
<c>OtpMbox.receive()</c> will never return <c>null</c>.</p>
<p>*** POTENTIAL INCOMPATIBILITY ***</p>
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
index 363fdb950a..fffb8475d3 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
@@ -102,7 +102,7 @@ public class OtpEpmd {
/**
* Set the port number to be used to contact the epmd process. Only needed
* when the default port is not desired and system environment variable
- * ERL_EPMD_PORT can not be read (applet).
+ * ERL_EPMD_PORT cannot be read (applet).
*/
public static void useEpmdPort(final int port) {
EpmdPort.set(port);
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
index ded8f6e1e5..6d81ce630b 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
@@ -601,7 +601,7 @@ public class OtpInputStream extends ByteArrayInputStream {
* @return the integer value.
*
* @exception OtpErlangDecodeException
- * if the next term in the stream can not be represented as a
+ * if the next term in the stream cannot be represented as a
* positive integer.
*/
public int read_uint() throws OtpErlangDecodeException {
@@ -622,7 +622,7 @@ public class OtpInputStream extends ByteArrayInputStream {
* @return the integer value.
*
* @exception OtpErlangDecodeException
- * if the next term in the stream can not be represented as
+ * if the next term in the stream cannot be represented as
* an integer.
*/
public int read_int() throws OtpErlangDecodeException {
@@ -643,7 +643,7 @@ public class OtpInputStream extends ByteArrayInputStream {
* @return the short value.
*
* @exception OtpErlangDecodeException
- * if the next term in the stream can not be represented as a
+ * if the next term in the stream cannot be represented as a
* positive short.
*/
public short read_ushort() throws OtpErlangDecodeException {
@@ -664,7 +664,7 @@ public class OtpInputStream extends ByteArrayInputStream {
* @return the short value.
*
* @exception OtpErlangDecodeException
- * if the next term in the stream can not be represented as a
+ * if the next term in the stream cannot be represented as a
* short.
*/
public short read_short() throws OtpErlangDecodeException {
@@ -685,7 +685,7 @@ public class OtpInputStream extends ByteArrayInputStream {
* @return the long value.
*
* @exception OtpErlangDecodeException
- * if the next term in the stream can not be represented as a
+ * if the next term in the stream cannot be represented as a
* positive long.
*/
public long read_ulong() throws OtpErlangDecodeException {
@@ -698,7 +698,7 @@ public class OtpInputStream extends ByteArrayInputStream {
* @return the long value.
*
* @exception OtpErlangDecodeException
- * if the next term in the stream can not be represented as a
+ * if the next term in the stream cannot be represented as a
* long.
*/
public long read_long() throws OtpErlangDecodeException {
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
index 42e178c3f6..29a8bc1540 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -156,7 +156,7 @@ public class OtpMbox {
* of the next message waiting in this mailbox.
*
* @exception OtpErlangDecodeException
- * if the message can not be decoded.
+ * if the message cannot be decoded.
*
* @exception OtpErlangExit
* if a linked {@link OtpErlangPid pid} has exited or has
@@ -184,7 +184,7 @@ public class OtpMbox {
* of the next message waiting in this mailbox.
*
* @exception OtpErlangDecodeException
- * if the message can not be decoded.
+ * if the message cannot be decoded.
*
* @exception OtpErlangExit
* if a linked {@link OtpErlangPid pid} has exited or has
diff --git a/lib/kernel/doc/src/.gitignore b/lib/kernel/doc/src/.gitignore
new file mode 100644
index 0000000000..c2813ac866
--- /dev/null
+++ b/lib/kernel/doc/src/.gitignore
@@ -0,0 +1 @@
+*.eps \ No newline at end of file
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index f34eee71ba..f8867ccf25 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -84,6 +84,7 @@ XML_CHAPTER_FILES = \
BOOK_FILES = book.xml
+# The .png file is generated from a .dia file with target 'update_png'
IMAGE_FILES = \
logger_arch.png
@@ -112,6 +113,17 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
+# FIGURES
+# ----------------------------------------------------
+# In order to update the figures you have to have both dia
+# and imagemagick installed.
+# The generated .png file must be committed.
+
+update_png:
+ dia --export=logger_arch.eps logger_arch.dia
+ convert logger_arch.eps -resize 65% logger_arch.png
+
+# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
@@ -142,12 +154,13 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~ *.eps
$(SPECDIR)/specs_erl_prim_loader_stub.xml:
$(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index aff3e8133c..69ce4da61c 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -538,7 +538,7 @@ zip:create("mnesia-4.4.7.ez",
</item>
<tag><c>not_purged</c></tag>
<item>
- <p>The object code can not be loaded because an old version
+ <p>The object code cannot be loaded because an old version
of the code already exists.</p>
</item>
<tag><c>sticky_directory</c></tag>
@@ -611,7 +611,7 @@ ok = code:finish_loading(Prepared),
<taglist>
<tag><c>not_purged</c></tag>
<item>
- <p>The object code can not be loaded because an old version
+ <p>The object code cannot be loaded because an old version
of the code already exists.</p>
</item>
<tag><c>sticky_directory</c></tag>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index e6a7962c5a..f281d61459 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -734,22 +734,23 @@ get_tcpi_sacked(Sock) ->
</item>
<tag><c>{buffer, Size}</c></tag>
<item>
- <p>The size of the user-level software buffer used by
- the driver.
- Not to be confused with options <c>sndbuf</c>
+ <p>The size of the user-level buffer used by
+ the driver. Not to be confused with options <c>sndbuf</c>
and <c>recbuf</c>, which correspond to the
- Kernel socket buffers. It is recommended
- to have <c>val(buffer) &gt;= max(val(sndbuf),val(recbuf))</c> to
+ Kernel socket buffers. For TCP it is recommended
+ to have <c>val(buffer) &gt;= val(recbuf)</c> to
avoid performance issues because of unnecessary copying.
+ For UDP the same recommendation applies, but the max should
+ not be larger than the MTU of the network path.
<c>val(buffer)</c> is automatically set to the above
- maximum when values <c>sndbuf</c> or <c>recbuf</c> are set.
- However, as the sizes set for <c>sndbuf</c> and <c>recbuf</c>
+ maximum when <c>recbuf</c> is set.
+ However, as the size set for <c>recbuf</c>
usually become larger, you are encouraged to use
<seealso marker="#getopts/2"><c>getopts/2</c></seealso>
to analyze the behavior of your operating system.</p>
<p>Note that this is also the maximum amount of data that can be
- received from a single recv call. If you are using higher than
- normal MTU consider setting buffer higher.</p>
+ received from a single recv call. If you are using higher than
+ normal MTU consider setting buffer higher.</p>
</item>
<tag><c>{delay_send, Boolean}</c></tag>
<item>
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index 3914226a3e..15dbdb47dc 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -192,7 +192,7 @@
<p>To change the primary log level at runtime, use
<seealso marker="logger#set_primary_config/2">
<c>logger:set_primary_config(level, Level)</c></seealso>.</p>
- <p>Defaults to <c>info</c>.</p>
+ <p>Defaults to <c>notice</c>.</p>
</item>
<tag><marker id="logger_sasl_compatible"/>
<c>logger_sasl_compatible = true | false</c></tag>
@@ -310,24 +310,31 @@
<tag><c>net_ticktime = TickTime</c></tag>
<item>
<marker id="net_ticktime"></marker>
- <p>Specifies the <c>net_kernel</c> tick time. <c>TickTime</c>
- is specified in seconds. Once every <c>TickTime/4</c> second, all
- connected nodes are ticked (if anything else is written
- to a node). If nothing is received from another node
- within the last four tick times, that node is considered
- to be down. This ensures that nodes that are not responding,
- for reasons such as hardware errors, are considered to be
- down.</p>
- <p>The time <c>T</c>, in which a node that is not responding is
- detected, is calculated as <c><![CDATA[MinT < T < MaxT]]></c>, where:</p>
+ <p>Specifies the <c>net_kernel</c> tick time in seconds. This is the
+ approximate time a connected node may be unresponsive until it is
+ considered down and thereby disconnected.</p>
+ <p>Once every <c>TickTime/4</c> seconds, each connected node is ticked
+ if nothing has been sent to it during that last <c>TickTime/4</c>
+ interval. A tick is a small package sent on the connection. A connected
+ node is considered to be down if no ticks or payload packages have been
+ received during the last four <c>TickTime/4</c> intervals. This ensures
+ that nodes that are not responding, for reasons such as hardware errors,
+ are considered to be down.</p>
+ <p>As the availability is only checked every <c>TickTime/4</c> seconds,
+ the actual time <c>T</c> a node have been unresponsive when
+ detected may vary between <c>MinT</c> and <c>MaxT</c>,
+ where:</p>
<code type="none">
MinT = TickTime - TickTime / 4
MaxT = TickTime + TickTime / 4</code>
- <p><c>TickTime</c> defaults to <c>60</c> (seconds). Thus,
- <c><![CDATA[45 < T < 75]]></c> seconds.</p>
- <p>Notice that <em>all</em> communicating nodes are to have the <em>same</em>
- <c>TickTime</c> value specified.</p>
- <p>Normally, a terminating node is detected immediately.</p>
+ <p><c>TickTime</c> defaults to <c>60</c> seconds. Thus,
+ <c><![CDATA[45 < T < 75]]></c> seconds.</p>
+ <p>Notice that <em>all</em> communicating nodes are to have the
+ <em>same</em> <c>TickTime</c> value specified, as it determines both the
+ frequency of outgoing ticks and the expected frequency of incominging
+ ticks.</p>
+ <p>Normally, a terminating node is detected immediately by the transport
+ protocol (like TCP/IP).</p>
</item>
<tag><c>shutdown_timeout = integer() | infinity</c></tag>
<item>
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
index 33f1919de0..a4d6efa2d8 100644
--- a/lib/kernel/doc/src/logger.xml
+++ b/lib/kernel/doc/src/logger.xml
@@ -98,46 +98,6 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
<datatypes>
<datatype>
- <name name="primary_config"/>
- <desc>
- <p>Primary configuration data for Logger. The following
- default values apply:</p>
- <list>
- <item><c>level => info</c></item>
- <item><c>filter_default => log</c></item>
- <item><c>filters => []</c></item>
- </list>
- </desc>
- </datatype>
- <datatype>
- <name name="handler_config"/>
- <desc>
- <p>Handler configuration data for Logger. The following
- default values apply:</p>
- <list>
- <item><c>level => all</c></item>
- <item><c>filter_default => log</c></item>
- <item><c>filters => []</c></item>
- <item><c>formatter => {logger_formatter, DefaultFormatterConfig</c>}</item>
- </list>
- <p>In addition to these, the following fields are
- automatically inserted by Logger, values taken from the
- two first parameters
- to <seealso marker="#add_handler-3"><c>add_handler/3</c></seealso>:</p>
- <list>
- <item><c>id => HandlerId</c></item>
- <item><c>module => Module</c></item>
- </list>
- <p>Handler specific configuration data is inserted by the
- handler callback itself, in a sub structure associated with
- the field named <c>config</c>.</p>
- <p>See the <seealso marker="logger_formatter#type-config">
- <c>logger_formatter(3)</c></seealso> manual page for
- information about the default configuration for this
- formatter.</p>
- </desc>
- </datatype>
- <datatype>
<name name="filter"/>
<desc>
<p>A filter which can be installed as a handler filter, or as
@@ -172,6 +132,39 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</desc>
</datatype>
<datatype>
+ <name name="handler_config"/>
+ <desc>
+ <p>Handler configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => all</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ <item><c>formatter => {logger_formatter, DefaultFormatterConfig</c>}</item>
+ </list>
+ <p>In addition to these, the following fields are
+ automatically inserted by Logger, values taken from the
+ two first parameters
+ to <seealso marker="#add_handler-3"><c>add_handler/3</c></seealso>:</p>
+ <list>
+ <item><c>id => HandlerId</c></item>
+ <item><c>module => Module</c></item>
+ </list>
+ <p>These are read-only and cannot be changed in runtime.</p>
+ <p>Handler specific configuration data is inserted by the
+ handler callback itself, in a sub structure associated with
+ the field named <c>config</c>. See
+ the <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>
+ manual pages for information about the specifc configuration
+ for these handlers.</p>
+ <p>See the <seealso marker="logger_formatter#type-config">
+ <c>logger_formatter(3)</c></seealso> manual page for
+ information about the default configuration for this
+ formatter.</p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="handler_id"/>
<desc>
<p>A unique identifier for a handler instance.</p>
@@ -234,7 +227,10 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
a <seealso marker="#type-report"><c>report()</c></seealso>,
the <c>report_cb</c> key can be associated with a fun
(report callback) that converts the report to a format
- string and arguments. See
+ string and arguments, or directly to a string. See the
+ type definition
+ of <seealso marker="#type-report_cb"><c>report_cb()</c></seealso>,
+ and
section <seealso marker="logger_chapter#log_message">Log
Message</seealso> in the User's Guide for more
information about report callbacks.</p>
@@ -249,12 +245,40 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
</desc>
</datatype>
<datatype>
+ <name name="primary_config"/>
+ <desc>
+ <p>Primary configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => info</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
<name name="report"/>
<desc>
<p></p>
</desc>
</datatype>
<datatype>
+ <name name="report_cb"/>
+ <desc>
+ <p>A fun which converts a <seealso marker="#type-report"><c>report()</c>
+ </seealso> to a format string and arguments, or directly to a string.
+ See section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the User's Guide for more
+ information.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report_cb_config"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="timestamp"/>
<desc>
<p>A timestamp produced
@@ -285,13 +309,16 @@ logger:error("error happened because: ~p", [Reason]). % Without macro
<item><c>?LOG_INFO(FunOrFormat,Args[,Metadata])</c></item>
<item><c>?LOG_DEBUG(StringOrReport[,Metadata])</c></item>
<item><c>?LOG_DEBUG(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG(Level,StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG(Level,FunOrFormat,Args[,Metadata])</c></item>
</list>
<p>All macros expand to a call to Logger, where <c>Level</c> is
- taken from the macro name, and location data is added to the
- metadata. See the description of
+ taken from the macro name, or from the first argument in the
+ case of the <c>?LOG</c> macro. Location data is added to the
+ metadata as described under
the <seealso marker="#type-metadata"><c>metadata()</c></seealso>
- type for more information about the location data.</p>
+ type definition.</p>
<p>The call is wrapped in a case statement and will be evaluated
only if <c>Level</c> is equal to or below the configured log
@@ -669,6 +696,17 @@ start(_, []) ->
</func>
<func>
+ <name name="set_application_level" arity="2"/>
+ <fsummary>Set the log level for all modules in the specified application.</fsummary>
+ <desc>
+ <p>Set the log level for all the modules of the specified application.</p>
+ <p>This function is a convenience function that calls
+ <seealso marker="#set_module_level/2">logger:set_module_level/2</seealso>
+ for each module associated with an application.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="set_handler_config" arity="2"/>
<fsummary>Set configuration data for the specified handler.</fsummary>
<desc>
@@ -690,15 +728,30 @@ start(_, []) ->
</func>
<func>
- <name name="set_handler_config" arity="3"/>
+ <name name="set_handler_config" arity="3" clause_i="1"/>
+ <name name="set_handler_config" arity="3" clause_i="2"/>
+ <name name="set_handler_config" arity="3" clause_i="3"/>
+ <name name="set_handler_config" arity="3" clause_i="4"/>
+ <name name="set_handler_config" arity="3" clause_i="5"/>
<fsummary>Add or update configuration data for the specified
handler.</fsummary>
+ <type variable="HandlerId"/>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <type variable="Formatter" name_i="4"/>
+ <type variable="Config" name_i="5"/>
+ <type variable="Return"/>
<desc>
<p>Add or update configuration data for the specified
handler. If the given <c><anno>Key</anno></c> already
exists, its associated value will be changed
- to <c><anno>Value</anno></c>. If it does not exist, it will
+ to the given value. If it does not exist, it will
be added.</p>
+ <p>See the definition of
+ the <seealso marker="#type-handler_config">
+ <c>handler_config()</c></seealso> type for more
+ information about the different parameters.</p>
</desc>
</func>
@@ -721,13 +774,18 @@ start(_, []) ->
</func>
<func>
- <name name="set_primary_config" arity="2"/>
+ <name name="set_primary_config" arity="2" clause_i="1"/>
+ <name name="set_primary_config" arity="2" clause_i="2"/>
+ <name name="set_primary_config" arity="2" clause_i="3"/>
<fsummary>Add or update primary configuration data for Logger.</fsummary>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
<desc>
<p>Add or update primary configuration data for Logger. If the
given <c><anno>Key</anno></c> already exists, its associated
- value will be changed to <c><anno>Value</anno></c>. If it
- does not exist, it will be added.</p>
+ value will be changed to the given value. If it does not
+ exist, it will be added.</p>
</desc>
</func>
@@ -735,8 +793,7 @@ start(_, []) ->
<name name="set_module_level" arity="2"/>
<fsummary>Set the log level for the specified modules.</fsummary>
<desc>
- <p>Set the log level for the
- specified modules.</p>
+ <p>Set the log level for the specified modules.</p>
<p>The log level for a module overrides the primary log level
of Logger for log events originating from the module in
question. Notice, however, that it does not override the
@@ -792,6 +849,17 @@ start(_, []) ->
</func>
<func>
+ <name name="unset_application_level" arity="1"/>
+ <fsummary>Unset the log level for all modules in the specified application.</fsummary>
+ <desc>
+ <p>Unset the log level for all the modules of the specified application.</p>
+ <p>This function is a convinience function that calls
+ <seealso marker="#unset_module_level/1">logger:unset_module_level/2</seealso>
+ for each module associated with an application.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="unset_module_level" arity="0"/>
<fsummary>Remove module specific log settings for all modules.</fsummary>
<desc>
diff --git a/lib/kernel/doc/src/logger_arch.dia b/lib/kernel/doc/src/logger_arch.dia
new file mode 100644
index 0000000000..97be31856e
--- /dev/null
+++ b/lib/kernel/doc/src/logger_arch.dia
Binary files differ
diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png
index a3a863c511..70933a5a41 100644
--- a/lib/kernel/doc/src/logger_arch.png
+++ b/lib/kernel/doc/src/logger_arch.png
Binary files differ
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
index f4a752bde9..c2cdf38a64 100644
--- a/lib/kernel/doc/src/logger_chapter.xml
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -69,6 +69,8 @@
figure shows two log handlers, but any number of handlers can be
installed.</p>
+ <!-- The image is edited with dia in logger_arch.dia file,
+ and .png file generated with make target 'png'. -->
<image file="logger_arch.png">
<icaption>Conceptual Overview</icaption>
</image>
@@ -192,10 +194,26 @@
the log event's <seealso marker="#metadata">metadata</seealso>.
The report callback is a convenience function that
the <seealso marker="#formatters">formatter</seealso> can use
- to convert the report to a format string and arguments. The
+ to convert the report to a format string and arguments, or
+ directly to a string. The
formatter can also use its own conversion function, if no
callback is provided, or if a customized formatting is
desired.</p>
+ <p>The report callback must be a fun with one or two
+ arguments. If it takes one argument, this is the report
+ itself, and the fun returns a format string and arguments:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>) -> {<seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso>,[term()]})</pre>
+ <p>If it takes two arguments, the first is the report, and the
+ second is a map containing extra data that allows direct
+ coversion to a string:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>,<seealso marker="logger#type-report_cb_config"><c>logger:report_cb_config()</c></seealso>) -> <seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c></seealso>)
+ </pre>
+ <p>The fun must obey the <c>encoding</c>, <c>depth</c>
+ and <c>chars_limit</c> parameters provided in the second
+ argument, as the formatter cannot do anything useful of these
+ parameters with the returned string. This variant is used when
+ the formatting of the report depends on the size and encoding
+ parameters.</p>
<p>Example, format string and arguments:</p>
<code>logger:error("The file does not exist: ~ts",[Filename])</code>
<p>Example, string:</p>
@@ -222,7 +240,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
with <seealso marker="logger#set_process_metadata-1">
<c>logger:set_process_metadata/1</c></seealso>
and <seealso marker="logger#update_process_metadata-1">
- <c>logger:update_process metadata/1</c></seealso>,
+ <c>logger:update_process_metadata/1</c></seealso>,
respectively. This metadata applies to the process on
which these calls are made, and Logger adds the metadata
to all log events issued on that process.</p>
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
index e777afaf86..5a060fd42b 100644
--- a/lib/kernel/doc/src/logger_formatter.xml
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -78,10 +78,17 @@
format controls ~p and ~w are replaced with ~P and ~W,
respectively, and the value is used as the depth
parameter. For details, see
- <seealso marker="stdlib:io#format-2">io:format/2,3</seealso>
+ <seealso marker="stdlib:io#format-2"><c>io:format/2,3</c></seealso>
in STDLIB.</p>
<p>Defaults to <c>unlimited</c>.</p>
</item>
+ <tag><c>encoding = </c><seealso marker="stdlib:unicode#type-encoding">
+ <c>unicode:encoding()</c></seealso></tag>
+ <item>
+ <p>This parameter must reflect the encoding of the device
+ that the handler prints to.</p>
+ <p>Defaults to <c>utf8</c></p>
+ </item>
<tag><c>legacy_header = boolean()</c></tag>
<item>
<p>If set to <c>true</c> a header field is added to
@@ -105,7 +112,8 @@
by <c>chars_limit</c> or <c>depth</c>, it is truncated.</p>
<p>Defaults to <c>unlimited</c>.</p>
</item>
- <tag><c>report_cb = fun((</c><seealso marker="logger#type-report"><c>logger:report()</c></seealso><c>) -> {</c><seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso><c>, [term()]})</c></tag>
+ <tag><c>report_cb = </c><seealso marker="logger#type-report_cb">
+ <c>logger:report_cb()</c></seealso></tag>
<item>
<p>A report callback is used by the formatter to transform
log messages on report form to a format string and
@@ -119,16 +127,19 @@
both the default report callback, and any report
callback found in metadata. That is, all reports are
converted by this configured function.</p>
- <p>The value must be a function with arity 1,
- returning <c>{Format,Args}</c>, and it will be called
- with a report as only argument.</p>
</item>
<tag><c>single_line = boolean()</c></tag>
<item>
- <p>If set to <c>true</c>, all newlines in the message are
- replaced with <c>", "</c>, and white spaces following
- directly after newlines are removed. Notice that newlines
- added by the <c>template</c> parameter are not replaced.</p>
+ <p>If set to <c>true</c>, each log event is printed as a
+ single line. To achieve this, <c>logger_formatter</c>
+ sets the field width to <c>0</c> for all <c>~p</c>
+ and <c>~P</c> control sequences in the format a string
+ (see <seealso marker="stdlib:io#format-2">
+ <c>io:format/2</c></seealso>), and replaces all
+ newlines in the message with <c>", "</c>. White spaces
+ following directly after newlines are removed. Notice
+ that newlines added by the <c>template</c> parameter are
+ not replaced.</p>
<p>Defaults to <c>true</c>.</p>
</item>
<tag><marker id="template"/>
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index a30d28d55a..d3bd7365e2 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -102,8 +102,10 @@ $ <input>erl -sname foobar</input></pre>
<fsummary>Establish a connection to a node.</fsummary>
<desc>
<p>Establishes a connection to <c><anno>Node</anno></c>. Returns
- <c>true</c> if successful, <c>false</c> if not, and <c>ignored</c>
- if the local node is not alive.</p>
+ <c>true</c> if a connection was established or was already
+ established or if <c><anno>Node</anno></c> is the local node
+ itself. Returns <c>false</c> if the connection attempt failed, and
+ <c>ignored</c> if the local node is not alive.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index e1ef8ab387..5884f93878 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -314,6 +314,42 @@
</section>
+<section><title>Kernel 5.4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Non semantic change in dist_util.erl to silence dialyzer
+ warning.</p>
+ <p>
+ Own Id: OTP-15170</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix some potential buggy behavior in how ticks are sent
+ on inter node distribution connections. Tick is now sent
+ to c-node even if there are unsent buffered data, as
+ c-nodes need ticks in order to send reply ticks. The
+ amount of sent data was calculated wrongly when ticks
+ where suppressed due to unsent buffered data.</p>
+ <p>
+ Own Id: OTP-15162 Aux Id: ERIERL-191 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 5.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/include/logger.hrl b/lib/kernel/include/logger.hrl
index 2143ccd297..b09977e0f2 100644
--- a/lib/kernel/include/logger.hrl
+++ b/lib/kernel/include/logger.hrl
@@ -32,6 +32,10 @@
-define(LOG_DEBUG(A,B),?DO_LOG(debug,[A,B])).
-define(LOG_DEBUG(A,B,C),?DO_LOG(debug,[A,B,C])).
+-define(LOG(L,A),?DO_LOG(L,[A])).
+-define(LOG(L,A,B),?DO_LOG(L,[A,B])).
+-define(LOG(L,A,B,C),?DO_LOG(L,[A,B,C])).
+
-define(LOCATION,#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},
line=>?LINE,
file=>?FILE}).
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index c595c25341..57f17defc8 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -112,7 +112,8 @@ MODULES = \
logger \
logger_backend \
logger_config \
- logger_std_h \
+ logger_handler_watcher \
+ logger_std_h \
logger_disk_log_h \
logger_h_common \
logger_filters \
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index a7e7f19167..ad8c937882 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -74,8 +74,8 @@ start() ->
type => worker,
modules => dynamic},
case supervisor:start_child(logger_sup, ErrorLogger) of
- {ok,_} ->
- ok;
+ {ok,Pid} ->
+ ok = logger_handler_watcher:register_handler(?MODULE,Pid);
Error ->
Error
end;
@@ -95,9 +95,14 @@ start_link() ->
%%% Stop the event manager
-spec stop() -> ok.
stop() ->
- _ = supervisor:terminate_child(logger_sup,?MODULE),
- _ = supervisor:delete_child(logger_sup,?MODULE),
- ok.
+ case whereis(?MODULE) of
+ undefined ->
+ ok;
+ _Pid ->
+ _ = gen_event:stop(?MODULE,{shutdown,stopped},infinity),
+ _ = supervisor:delete_child(logger_sup,?MODULE),
+ ok
+ end.
%%%-----------------------------------------------------------------
%%% Callbacks for logger
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index 1270de4144..c4d276f9e8 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -36,7 +36,8 @@
map_info/1, same/2, set_internal_state/2,
size_shared/1, copy_shared/1, dirty_cpu/2, dirty_io/2, dirty/3,
lcnt_control/1, lcnt_control/2, lcnt_collect/0, lcnt_clear/0,
- lc_graph/0, lc_graph_to_dot/2, lc_graph_merge/2]).
+ lc_graph/0, lc_graph_to_dot/2, lc_graph_merge/2,
+ alloc_blocks_size/1]).
-spec breakpoint(MFA, Flag) -> non_neg_integer() when
MFA :: {Module :: module(),
@@ -495,3 +496,58 @@ lcg_print_locks(Out, [LastLock]) ->
lcg_print_locks(Out, [Lock | Rest]) ->
io:format(Out, "~w,\n", [Lock]),
lcg_print_locks(Out, Rest).
+
+
+%% Returns the amount of memory allocated by the given allocator type.
+-spec alloc_blocks_size(Type) -> non_neg_integer() | undefined when
+ Type :: atom().
+
+alloc_blocks_size(Type) ->
+ Allocs = erlang:system_info(alloc_util_allocators),
+ Sizes = erlang:system_info({allocator_sizes, Allocs}),
+ alloc_blocks_size_1(Sizes, Type, 0).
+
+alloc_blocks_size_1([], _Type, 0) ->
+ undefined;
+alloc_blocks_size_1([{_Type, false} | Rest], Type, Acc) ->
+ alloc_blocks_size_1(Rest, Type, Acc);
+alloc_blocks_size_1([{Type, Instances} | Rest], Type, Acc0) ->
+ F = fun ({instance, _, L}, Acc) ->
+ MBCSPool = case lists:keyfind(mbcs_pool, 1, L) of
+ {_, Pool} -> Pool;
+ false -> []
+ end,
+ {_,MBCS} = lists:keyfind(mbcs, 1, L),
+ {_,SBCS} = lists:keyfind(sbcs, 1, L),
+ Acc +
+ sum_block_sizes(MBCSPool) +
+ sum_block_sizes(MBCS) +
+ sum_block_sizes(SBCS)
+ end,
+ alloc_blocks_size_1(Rest, Type, lists:foldl(F, Acc0, Instances));
+alloc_blocks_size_1([{_Type, Instances} | Rest], Type, Acc0) ->
+ F = fun ({instance, _, L}, Acc) ->
+ Acc + sum_foreign_sizes(Type, L)
+ end,
+ alloc_blocks_size_1(Rest, Type, lists:foldl(F, Acc0, Instances));
+alloc_blocks_size_1([], _Type, Acc) ->
+ Acc.
+
+sum_foreign_sizes(Type, L) ->
+ case lists:keyfind(mbcs_pool, 1, L) of
+ {_,Pool} ->
+ {_,ForeignBlocks} = lists:keyfind(foreign_blocks, 1, Pool),
+ case lists:keyfind(Type, 1, ForeignBlocks) of
+ {_,TypeSizes} -> sum_block_sizes(TypeSizes);
+ false -> 0
+ end;
+ _ ->
+ 0
+ end.
+
+sum_block_sizes(Blocks) ->
+ lists:foldl(
+ fun({blocks_size, Sz,_,_}, Sz0) -> Sz0+Sz;
+ ({blocks_size, Sz}, Sz0) -> Sz0+Sz;
+ (_, Sz) -> Sz
+ end, 0, Blocks).
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 9f76360b8b..e771461b65 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -98,7 +98,7 @@ init() ->
{win32,WinType} ->
win32_load_from_registry(WinType);
_ ->
- error("can not read win32 system registry~n", [])
+ error("cannot read win32 system registry~n", [])
end
end, CfgFiles),
diff --git a/lib/kernel/src/inet_dns.erl b/lib/kernel/src/inet_dns.erl
index f1f58bc872..6c98d2aab7 100644
--- a/lib/kernel/src/inet_dns.erl
+++ b/lib/kernel/src/inet_dns.erl
@@ -699,7 +699,7 @@ encode_labels(Bin, Comp0, Pos, [L|Ls]=Labels)
none ->
Comp = if Pos < (3 bsl 14) ->
%% Just in case - compression
- %% pointers can not reach further
+ %% pointers cannot reach further
gb_trees:insert(Labels, Pos, Comp0);
true -> Comp0
end,
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 47dd7c03d5..4933eae76f 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -67,6 +67,7 @@
logger_filters,
logger_formatter,
logger_h_common,
+ logger_handler_watcher,
logger_server,
logger_simple_h,
logger_std_h,
@@ -129,6 +130,7 @@
kernel_refc,
kernel_sup,
logger,
+ logger_handler_watcher,
logger_sup,
net_kernel,
net_sup,
diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
index 0a9b1672ec..0020fe220b 100644
--- a/lib/kernel/src/logger.erl
+++ b/lib/kernel/src/logger.erl
@@ -39,6 +39,7 @@
remove_primary_filter/1, remove_handler_filter/2,
set_module_level/2,
unset_module_level/1, unset_module_level/0,
+ set_application_level/2, unset_application_level/1,
get_module_level/0, get_module_level/1,
set_primary_config/1, set_primary_config/2,
set_handler_config/2, set_handler_config/3,
@@ -74,6 +75,11 @@
-type level() :: emergency | alert | critical | error |
warning | notice | info | debug.
-type report() :: map() | [{atom(),term()}].
+-type report_cb() :: fun((report()) -> {io:format(),[term()]}) |
+ fun((report(),report_cb_config()) -> unicode:chardata()).
+-type report_cb_config() :: #{encoding := unicode:encoding(),
+ depth := pos_integer() | unlimited,
+ chars_limit := pos_integer() | unlimited}.
-type msg_fun() :: fun((term()) -> {io:format(),[term()]} |
report() |
unicode:chardata()).
@@ -84,7 +90,7 @@
file => file:filename(),
line => non_neg_integer(),
domain => [atom()],
- report_cb => fun((report()) -> {io:format(),[term()]}),
+ report_cb => report_cb(),
atom() => term()}.
-type location() :: #{mfa := {module(),atom(),non_neg_integer()},
file := file:filename(),
@@ -110,10 +116,22 @@
-type config_handler() :: {handler, handler_id(), module(), handler_config()}.
--export_type([log_event/0,level/0,report/0,msg_fun/0,metadata/0,
- primary_config/0,handler_config/0,handler_id/0,
- filter_id/0,filter/0,filter_arg/0,filter_return/0,
- config_handler/0,formatter_config/0]).
+-export_type([log_event/0,
+ level/0,
+ report/0,
+ report_cb/0,
+ report_cb_config/0,
+ msg_fun/0,
+ metadata/0,
+ primary_config/0,
+ handler_config/0,
+ handler_id/0,
+ filter_id/0,
+ filter/0,
+ filter_arg/0,
+ filter_return/0,
+ config_handler/0,
+ formatter_config/0]).
%%%-----------------------------------------------------------------
%%% API
@@ -352,9 +370,12 @@ add_handler(HandlerId,Module,Config) ->
remove_handler(HandlerId) ->
logger_server:remove_handler(HandlerId).
--spec set_primary_config(Key,Value) -> ok | {error,term()} when
- Key :: atom(),
- Value :: term().
+-spec set_primary_config(level,Level) -> ok | {error,term()} when
+ Level :: level() | all | none;
+ (filter_default,FilterDefault) -> ok | {error,term()} when
+ FilterDefault :: log | stop;
+ (filters,Filters) -> ok | {error,term()} when
+ Filters :: [{filter_id(),filter()}].
set_primary_config(Key,Value) ->
logger_server:set_config(primary,Key,Value).
@@ -363,10 +384,26 @@ set_primary_config(Key,Value) ->
set_primary_config(Config) ->
logger_server:set_config(primary,Config).
--spec set_handler_config(HandlerId,Key,Value) -> ok | {error,term()} when
+-spec set_handler_config(HandlerId,level,Level) -> Return when
HandlerId :: handler_id(),
- Key :: atom(),
- Value :: term().
+ Level :: level() | all | none,
+ Return :: ok | {error,term()};
+ (HandlerId,filter_default,FilterDefault) -> Return when
+ HandlerId :: handler_id(),
+ FilterDefault :: log | stop,
+ Return :: ok | {error,term()};
+ (HandlerId,filters,Filters) -> Return when
+ HandlerId :: handler_id(),
+ Filters :: [{filter_id(),filter()}],
+ Return :: ok | {error,term()};
+ (HandlerId,formatter,Formatter) -> Return when
+ HandlerId :: handler_id(),
+ Formatter :: {module(), formatter_config()},
+ Return :: ok | {error,term()};
+ (HandlerId,config,Config) -> Return when
+ HandlerId :: handler_id(),
+ Config :: term(),
+ Return :: ok | {error,term()}.
set_handler_config(HandlerId,Key,Value) ->
logger_server:set_config(HandlerId,Key,Value).
@@ -452,6 +489,27 @@ unset_module_level(Modules) ->
unset_module_level() ->
logger_server:unset_module_level().
+-spec set_application_level(Application,Level) -> ok | {error, not_loaded} when
+ Application :: atom(),
+ Level :: level() | all | none.
+set_application_level(App,Level) ->
+ case application:get_key(App, modules) of
+ {ok, Modules} ->
+ set_module_level(Modules, Level);
+ undefined ->
+ {error, {not_loaded, App}}
+ end.
+
+-spec unset_application_level(Application) -> ok | {error, not_loaded} when
+ Application :: atom().
+unset_application_level(App) ->
+ case application:get_key(App, modules) of
+ {ok, Modules} ->
+ unset_module_level(Modules);
+ undefined ->
+ {error, {not_loaded, App}}
+ end.
+
-spec get_module_level(Modules) -> [{Module,Level}] when
Modules :: [Module] | Module,
Module :: module(),
@@ -651,7 +709,7 @@ get_logger_type() ->
get_logger_level() ->
case application:get_env(kernel,logger_level,info) of
- Level when ?IS_LEVEL(Level) ->
+ Level when ?IS_LEVEL(Level); Level=:=all; Level=:=none ->
Level;
Level ->
throw({logger_level, Level})
diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl
index 0a72654e11..e56531c3cb 100644
--- a/lib/kernel/src/logger_disk_log_h.erl
+++ b/lib/kernel/src/logger_disk_log_h.erl
@@ -488,7 +488,8 @@ start(Name, Config, HandlerState) ->
type => worker,
modules => [?MODULE]},
case supervisor:start_child(logger_sup, LoggerDLH) of
- {ok,_Pid,Config1} ->
+ {ok,Pid,Config1} ->
+ ok = logger_handler_watcher:register_handler(Name,Pid),
{ok,Config1};
Error ->
Error
@@ -506,8 +507,11 @@ stop(Name) ->
%% system termination in order to avoid circular attempts
%% at removing the handler (implying deadlocks and
%% timeouts).
+ %% And we don't need to do supervisor:delete_child, since
+ %% the restart type is temporary, which means that the
+ %% child specification is automatically removed from the
+ %% supervisor when the process dies.
_ = gen_server:call(Pid, stop),
- _ = supervisor:delete_child(logger_sup, Name),
ok
end.
diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl
index 456b0c9e8d..b0d4adc14d 100644
--- a/lib/kernel/src/logger_formatter.erl
+++ b/lib/kernel/src/logger_formatter.erl
@@ -26,16 +26,17 @@
%%%-----------------------------------------------------------------
%%% Types
--type config() :: #{chars_limit=>pos_integer()| unlimited,
- depth=>pos_integer() | unlimited,
- legacy_header=>boolean(),
- max_size=>pos_integer() | unlimited,
- report_cb=>fun((logger:report()) -> {io:format(),[term()]}),
- single_line=>boolean(),
- template=>template(),
- time_designator=>byte(),
- time_offset=>integer()|[byte()]}.
--type template() :: [metakey()|{metakey(),template(),template()}|string()].
+-type config() :: #{chars_limit => pos_integer() | unlimited,
+ depth => pos_integer() | unlimited,
+ encoding => unicode:encoding(),
+ legacy_header => boolean(),
+ max_size => pos_integer() | unlimited,
+ report_cb => logger:report_cb(),
+ single_line => boolean(),
+ template => template(),
+ time_designator => byte(),
+ time_offset => integer() | [byte()]}.
+-type template() :: [metakey() | {metakey(),template(),template()} | string()].
-type metakey() :: atom() | [atom()].
%%%-----------------------------------------------------------------
@@ -76,7 +77,7 @@ format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0)
%% Trim leading and trailing whitespaces, and replace
%% newlines with ", "
re:replace(string:trim(MsgStr0),",?\r?\n\s*",", ",
- [{return,list},global]);
+ [{return,list},global,unicode]);
_false ->
MsgStr0
end;
@@ -119,78 +120,119 @@ value(_,_) ->
to_string(time,Time,Config) ->
format_time(Time,Config);
-to_string(mfa,MFA,_Config) ->
- format_mfa(MFA);
-to_string(_,Value,_Config) ->
- to_string(Value).
+to_string(mfa,MFA,Config) ->
+ format_mfa(MFA,Config);
+to_string(_,Value,Config) ->
+ to_string(Value,Config).
-to_string(X) when is_atom(X) ->
+to_string(X,_) when is_atom(X) ->
atom_to_list(X);
-to_string(X) when is_integer(X) ->
+to_string(X,_) when is_integer(X) ->
integer_to_list(X);
-to_string(X) when is_pid(X) ->
+to_string(X,_) when is_pid(X) ->
pid_to_list(X);
-to_string(X) when is_reference(X) ->
+to_string(X,_) when is_reference(X) ->
ref_to_list(X);
-to_string(X) when is_list(X) ->
- case io_lib:printable_unicode_list(lists:flatten(X)) of
+to_string(X,Config) when is_list(X) ->
+ case printable_list(lists:flatten(X)) of
true -> X;
- _ -> io_lib:format("~tp",[X])
+ _ -> io_lib:format(p(Config),[X])
end;
-to_string(X) ->
- io_lib:format("~tp",[X]).
+to_string(X,Config) ->
+ io_lib:format(p(Config),[X]).
+
+printable_list([]) ->
+ false;
+printable_list(X) ->
+ io_lib:printable_list(X).
format_msg({string,Chardata},Meta,Config) ->
- format_msg({"~ts",[Chardata]},Meta,Config);
-format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config) when is_function(Fun,1) ->
+ format_msg({s(Config),[Chardata]},Meta,Config);
+format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config)
+ when is_function(Fun,1); is_function(Fun,2) ->
format_msg(Msg,Meta#{report_cb=>Fun},maps:remove(report_cb,Config));
format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,1) ->
try Fun(Report) of
{Format,Args} when is_list(Format), is_list(Args) ->
format_msg({Format,Args},maps:remove(report_cb,Meta),Config);
Other ->
- format_msg({"REPORT_CB ERROR: ~tp; Returned: ~tp",
+ P = p(Config),
+ format_msg({"REPORT_CB/1 ERROR: "++P++"; Returned: "++P,
+ [Report,Other]},Meta,Config)
+ catch C:R:S ->
+ P = p(Config),
+ format_msg({"REPORT_CB/1 CRASH: "++P++"; Reason: "++P,
+ [Report,{C,R,logger:filter_stacktrace(?MODULE,S)}]},
+ Meta,Config)
+ end;
+format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,2) ->
+ try Fun(Report,maps:with([encoding,depth,chars_limit],Config)) of
+ String when ?IS_STRING(String) ->
+ try unicode:characters_to_list(String)
+ catch _:_ ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
+ [Report,String]},Meta,Config)
+ end;
+ Other ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
[Report,Other]},Meta,Config)
- catch C:R ->
- format_msg({"REPORT_CB CRASH: ~tp; Reason: ~tp",
- [Report,{C,R}]},Meta,Config)
+ catch C:R:S ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 CRASH: "++P++"; Reason: "++P,
+ [Report,{C,R,logger:filter_stacktrace(?MODULE,S)}]},
+ Meta,Config)
end;
format_msg({report,Report},Meta,Config) ->
format_msg({report,Report},
Meta#{report_cb=>fun logger:format_report/1},
Config);
-format_msg(Msg,_Meta,#{depth:=Depth,chars_limit:=CharsLimit}) ->
- limit_size(Msg, Depth, CharsLimit).
-
-limit_size(Msg,Depth,unlimited) ->
- limit_size(Msg,Depth,[]);
-limit_size(Msg,Depth,CharsLimit) when is_integer(CharsLimit) ->
- limit_size(Msg,Depth,[{chars_limit,CharsLimit}]);
-limit_size({Format,Args},unlimited,Opts) when is_list(Opts) ->
- try io_lib:format(Format,Args,Opts)
- catch _:_ ->
- io_lib:format("FORMAT ERROR: ~tp - ~tp",[Format,Args],Opts)
- end;
-limit_size({Format0,Args},Depth,Opts) when is_integer(Depth) ->
+format_msg(Msg,_Meta,#{depth:=Depth,chars_limit:=CharsLimit,
+ encoding:=Enc,single_line:=Single}) ->
+ Opts = chars_limit_to_opts(CharsLimit),
+ format_msg(Msg, Depth, Opts, Enc, Single).
+
+chars_limit_to_opts(unlimited) -> [];
+chars_limit_to_opts(CharsLimit) -> [{chars_limit,CharsLimit}].
+
+format_msg({Format0,Args},Depth,Opts,Enc,Single) ->
try
Format1 = io_lib:scan_format(Format0, Args),
- Format = limit_format(Format1, Depth),
+ Format = reformat(Format1, Depth, Single),
io_lib:build_text(Format,Opts)
- catch _:_ ->
- limit_size({"FORMAT ERROR: ~tp - ~tp",[Format0,Args]},Depth,Opts)
+ catch C:R:S ->
+ P = p(Enc,Single),
+ FormatError = "FORMAT ERROR: "++P++" - "++P,
+ case Format0 of
+ FormatError ->
+ %% already been here - avoid failing cyclically
+ erlang:raise(C,R,S);
+ _ ->
+ format_msg({FormatError,[Format0,Args]},
+ Depth,Opts,Enc,Single)
+ end
end.
-limit_format([#{control_char:=C0}=M0|T], Depth) when C0 =:= $p;
- C0 =:= $w ->
- C = C0 - ($a - $A), %To uppercase.
- #{args:=Args} = M0,
- M = M0#{control_char:=C,args:=Args++[Depth]},
- [M|limit_format(T, Depth)];
-limit_format([H|T], Depth) ->
- [H|limit_format(T, Depth)];
-limit_format([], _) ->
+reformat(Format,unlimited,false) ->
+ Format;
+reformat([#{control_char:=C}=M|T], Depth, true) when C =:= $p ->
+ [limit_depth(M#{width => 0}, Depth)|reformat(T, Depth, true)];
+reformat([#{control_char:=C}=M|T], Depth, true) when C =:= $P ->
+ [M#{width => 0}|reformat(T, Depth, true)];
+reformat([#{control_char:=C}=M|T], Depth, Single) when C =:= $p; C =:= $w ->
+ [limit_depth(M, Depth)|reformat(T, Depth, Single)];
+reformat([H|T], Depth, Single) ->
+ [H|reformat(T, Depth, Single)];
+reformat([], _, _) ->
[].
+limit_depth(M0, unlimited) ->
+ M0;
+limit_depth(#{control_char:=C0, args:=Args}=M0, Depth) ->
+ C = C0 - ($a - $A), %To uppercase.
+ M0#{control_char:=C,args:=Args++[Depth]}.
+
truncate(String,unlimited) ->
String;
truncate(String,Size) ->
@@ -225,22 +267,23 @@ timestamp_to_datetimemicro(SysTime,Config) when is_integer(SysTime) ->
end,
{Date,Time,Micro,UtcStr}.
-format_mfa({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->
+format_mfa({M,F,A},_) when is_atom(M), is_atom(F), is_integer(A) ->
atom_to_list(M)++":"++atom_to_list(F)++"/"++integer_to_list(A);
-format_mfa({M,F,A}) when is_atom(M), is_atom(F), is_list(A) ->
- format_mfa({M,F,length(A)});
-format_mfa(MFA) ->
- to_string(MFA).
+format_mfa({M,F,A},Config) when is_atom(M), is_atom(F), is_list(A) ->
+ format_mfa({M,F,length(A)},Config);
+format_mfa(MFA,Config) ->
+ to_string(MFA,Config).
maybe_add_legacy_header(Level,
#{time:=Timestamp}=Meta,
#{legacy_header:=true}=Config) ->
#{title:=Title}=MyMeta = add_legacy_title(Level,Meta,Config),
- {{Y,Mo,D},{H,Mi,S},Micro,UtcStr} =
+ {{Y,Mo,D},{H,Mi,Sec},Micro,UtcStr} =
timestamp_to_datetimemicro(Timestamp,Config),
+ S = s(Config),
Header =
- io_lib:format("=~ts==== ~w-~s-~4w::~2..0w:~2..0w:~2..0w.~6..0w ~s===",
- [Title,D,month(Mo),Y,H,Mi,S,Micro,UtcStr]),
+ io_lib:format("="++S++"==== ~w-~s-~4w::~2..0w:~2..0w:~2..0w.~6..0w ~s===",
+ [Title,D,month(Mo),Y,H,Mi,Sec,Micro,UtcStr]),
Meta#{?MODULE=>MyMeta#{header=>Header}};
maybe_add_legacy_header(_,Meta,_) ->
Meta.
@@ -280,10 +323,11 @@ month(12) -> "Dec".
%% configuration map
add_default_config(Config0) ->
Default =
- #{legacy_header=>false,
+ #{chars_limit=>unlimited,
+ encoding=>utf8,
error_logger_notice_header=>info,
+ legacy_header=>false,
single_line=>true,
- chars_limit=>unlimited,
time_designator=>$T},
MaxSize = get_max_size(maps:get(max_size,Config0,undefined)),
Depth = get_depth(maps:get(depth,Config0,undefined)),
@@ -369,7 +413,8 @@ do_check_config([{legacy_header,LH}|Config]) when is_boolean(LH) ->
do_check_config([{error_logger_notice_header,ELNH}|Config]) when ELNH == info;
ELNH == notice ->
do_check_config(Config);
-do_check_config([{report_cb,RCB}|Config]) when is_function(RCB,1) ->
+do_check_config([{report_cb,RCB}|Config]) when is_function(RCB,1);
+ is_function(RCB,2) ->
do_check_config(Config);
do_check_config([{template,T}|Config]) ->
case check_template(T) of
@@ -456,3 +501,26 @@ check_timezone(Tz) ->
catch _:_ ->
error
end.
+
+p(#{encoding:=Enc, single_line:=Single}) ->
+ p(Enc,Single).
+
+p(Enc,Single) ->
+ "~"++p_width(Single)++p_char(Enc).
+
+p_width(true) ->
+ "0";
+p_width(false) ->
+ "".
+
+p_char(latin1) ->
+ "p";
+p_char(_) ->
+ "tp".
+
+s(#{encoding:=Enc}) ->
+ s(Enc);
+s(latin1) ->
+ "~s";
+s(_) ->
+ "~ts".
diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl
index a40345dddc..854e5479b9 100644
--- a/lib/kernel/src/logger_h_common.erl
+++ b/lib/kernel/src/logger_h_common.erl
@@ -309,19 +309,6 @@ stop_or_restart(Name, {shutdown,Reason={overloaded,_Name,_QLen,_Mem}},
end,
spawn(RemoveAndRestart),
ok;
-
-stop_or_restart(Name, shutdown, _State) ->
- %% Probably terminated by supervisor. Remove the handler to avoid
- %% error printouts due to failing handler.
- _ = case logger:get_handler_config(Name) of
- {ok,_} ->
- %% Spawning to avoid deadlock
- spawn(logger,remove_handler,[Name]);
- _ ->
- ok
- end,
- ok;
-
stop_or_restart(_Name, _Reason, _State) ->
ok.
diff --git a/lib/kernel/src/logger_handler_watcher.erl b/lib/kernel/src/logger_handler_watcher.erl
new file mode 100644
index 0000000000..b75c74c643
--- /dev/null
+++ b/lib/kernel/src/logger_handler_watcher.erl
@@ -0,0 +1,113 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_handler_watcher).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+-export([register_handler/2]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {handlers}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+-spec start_link() -> {ok, Pid :: pid()} |
+ {error, Error :: {already_started, pid()}} |
+ {error, Error :: term()} |
+ ignore.
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+-spec register_handler(Id::logger:handler_id(),Pid::pid()) -> ok.
+register_handler(Id,Pid) ->
+ gen_server:call(?SERVER,{register,Id,Pid}).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+-spec init(Args :: term()) -> {ok, State :: term()} |
+ {ok, State :: term(), Timeout :: timeout()} |
+ {ok, State :: term(), hibernate} |
+ {stop, Reason :: term()} |
+ ignore.
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, #state{handlers=[]}}.
+
+-spec handle_call(Request :: term(), From :: {pid(), term()}, State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), Timeout :: timeout()} |
+ {reply, Reply :: term(), NewState :: term(), hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+handle_call({register,Id,Pid}, _From, #state{handlers=Hs}=State) ->
+ Ref = erlang:monitor(process,Pid),
+ Hs1 = lists:keystore(Id,1,Hs,{Id,Ref}),
+ {reply, ok, State#state{handlers=Hs1}}.
+
+-spec handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+-spec handle_info(Info :: timeout() | term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: normal | term(), NewState :: term()}.
+handle_info({'DOWN',Ref,process,_,shutdown}, #state{handlers=Hs}=State) ->
+ case lists:keytake(Ref,2,Hs) of
+ {value,{Id,Ref},Hs1} ->
+ %% Probably terminated by supervisor. Remove the handler to avoid
+ %% error printouts due to failing handler.
+ _ = case logger:get_handler_config(Id) of
+ {ok,_} ->
+ logger:remove_handler(Id);
+ _ ->
+ ok
+ end,
+ {noreply,State#state{handlers=Hs1}};
+ false ->
+ {noreply, State}
+ end;
+handle_info({'DOWN',Ref,process,_,_OtherReason}, #state{handlers=Hs}=State) ->
+ {noreply,State#state{handlers=lists:keydelete(Ref,2,Hs)}};
+handle_info(_Other,State) ->
+ {noreply,State}.
+
+-spec terminate(Reason :: normal | shutdown | {shutdown, term()} | term(),
+ State :: term()) -> any().
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl
index 28e31d46ea..644fdd5af2 100644
--- a/lib/kernel/src/logger_server.erl
+++ b/lib/kernel/src/logger_server.erl
@@ -83,7 +83,7 @@ set_module_level(Modules,Level) when is_list(Modules) ->
Error -> Error
end;
false ->
- {error,{not_a_list_of_modles,Modules}}
+ {error,{not_a_list_of_modules,Modules}}
end;
set_module_level(Modules,_) ->
{error,{not_a_list_of_modules,Modules}}.
@@ -96,7 +96,7 @@ unset_module_level(Modules) when is_list(Modules) ->
true ->
call({unset_module_level,Modules});
false ->
- {error,{not_a_list_of_modles,Modules}}
+ {error,{not_a_list_of_modules,Modules}}
end;
unset_module_level(Modules) ->
{error,{not_a_list_of_modules,Modules}}.
diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl
index 480fafd6d8..9a2a1443b3 100644
--- a/lib/kernel/src/logger_std_h.erl
+++ b/lib/kernel/src/logger_std_h.erl
@@ -467,7 +467,8 @@ start(Name, Config, HandlerState) ->
type => worker,
modules => [?MODULE]},
case supervisor:start_child(logger_sup, LoggerStdH) of
- {ok,_Pid,Config1} ->
+ {ok,Pid,Config1} ->
+ ok = logger_handler_watcher:register_handler(Name,Pid),
{ok,Config1};
Error ->
Error
@@ -485,8 +486,11 @@ stop(Name) ->
%% system termination in order to avoid circular attempts
%% at removing the handler (implying deadlocks and
%% timeouts).
+ %% And we don't need to do supervisor:delete_child, since
+ %% the restart type is temporary, which means that the
+ %% child specification is automatically removed from the
+ %% supervisor when the process dies.
_ = gen_server:call(Pid, stop),
- _ = supervisor:delete_child(logger_sup, Name),
ok
end.
diff --git a/lib/kernel/src/logger_sup.erl b/lib/kernel/src/logger_sup.erl
index dcdcdad0bd..3d6f482e20 100644
--- a/lib/kernel/src/logger_sup.erl
+++ b/lib/kernel/src/logger_sup.erl
@@ -46,7 +46,11 @@ init([]) ->
intensity => 1,
period => 5},
- {ok, {SupFlags, []}}.
+ Watcher = #{id => logger_handler_watcher,
+ start => {logger_handler_watcher, start_link, []},
+ shutdown => brutal_kill},
+
+ {ok, {SupFlags, [Watcher]}}.
%%%===================================================================
%%% Internal functions
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index c4e1a0ce1e..bea08242d8 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -472,7 +472,7 @@ handle_call({passive_cnct, Node}, From, State) ->
%% Explicit connect
%% The response is delayed until the connection is up and running.
%%
-handle_call({connect, _, Node, _, _}, From, State) when Node =:= node() ->
+handle_call({connect, _, Node}, From, State) when Node =:= node() ->
async_reply({reply, true, State}, From);
handle_call({connect, Type, Node}, From, State) ->
verbose({connect, Type, Node}, 1, State),
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 9c6712ad74..0e13f0383e 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -25,6 +25,7 @@
init_per_group/2,end_per_group/2]).
-export([tick/1, tick_change/1,
+ connect_node/1,
nodenames/1, hostnames/1,
illegal_nodenames/1, hidden_node/1,
setopts/1,
@@ -70,6 +71,7 @@ suite() ->
all() ->
[tick, tick_change, nodenames, hostnames, illegal_nodenames,
+ connect_node,
hidden_node, setopts,
table_waste, net_setuptime, inet_dist_options_options,
{group, monitor_nodes}].
@@ -106,6 +108,12 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
end_per_testcase(_Func, _Config) ->
ok.
+connect_node(Config) when is_list(Config) ->
+ Connected = nodes(connected),
+ true = net_kernel:connect_node(node()),
+ Connected = nodes(connected),
+ ok.
+
tick(Config) when is_list(Config) ->
PaDir = filename:dirname(code:which(erl_distribution_SUITE)),
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 23913ac56a..e784c06865 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1367,6 +1367,10 @@ file_info_basic_file(Config) when is_list(Config) ->
io:put_chars(Fd1, "foo bar"),
ok = ?FILE_MODULE:close(Fd1),
+ %% Don't crash the file server when passing incorrect arguments.
+ {error,badarg} = ?FILE_MODULE:read_file_info(Name, [{time, gurka}]),
+ {error,badarg} = ?FILE_MODULE:read_file_info([#{} | gaffel]),
+
%% Test that the file has the expected attributes.
%% The times are tricky, so we will save them to a separate test case.
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name),
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index b39399b18a..3acfff929e 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -34,7 +34,7 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-export([send_to_closed/1, active_n/1,
- buffer_size/1, binary_passive_recv/1, bad_address/1,
+ buffer_size/1, binary_passive_recv/1, max_buffer_size/1, bad_address/1,
read_packets/1, open_fd/1, connect/1, implicit_inet6/1,
local_basic/1, local_unbound/1,
local_fdopen/1, local_fdopen_unbound/1, local_abstract/1]).
@@ -44,7 +44,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [send_to_closed, buffer_size, binary_passive_recv,
+ [send_to_closed, buffer_size, binary_passive_recv, max_buffer_size,
bad_address, read_packets, open_fd, connect,
implicit_inet6, active_n,
{group, local}].
@@ -237,6 +237,14 @@ buffer_size_server_recv(Socket, IP, Port, Cnt) ->
end.
+%%-------------------------------------------------------------
+%% OTP-15206: Keep buffer small for udp
+%%-------------------------------------------------------------
+max_buffer_size(Config) when is_list(Config) ->
+ {ok, Socket} = gen_udp:open(0, [binary]),
+ ok = inet:setopts(Socket,[{recbuf, 1 bsl 20}]),
+ {ok, [{buffer, 65536}]} = inet:getopts(Socket,[buffer]),
+ gen_udp:close(Socket).
%%-------------------------------------------------------------
%% OTP-3823 gen_udp:recv does not return address in binary mode
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 2e5f8c7d2c..713de8c9a8 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -97,7 +97,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(lookup_bad_search_option, Config) ->
Db = inet_db,
Key = res_lookup,
- %% The bad option can not enter through inet_db:set_lookup/1,
+ %% The bad option cannot enter through inet_db:set_lookup/1,
%% but through e.g .inetrc.
Prev = ets:lookup(Db, Key),
ets:delete(Db, Key),
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index df6e48abae..cbec8d430c 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -531,7 +531,7 @@ edns0(Config) when is_list(Config) ->
case os:version() of
{M,V,_} when M < 5; M == 5, V =< 8 ->
%% In our test park only known platform
- %% with an DNS resolver that can not do
+ %% with an DNS resolver that cannot do
%% EDNS0.
{comment,"No EDNS0"}
end
diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl
index b367b4dd54..6bd9b20c35 100644
--- a/lib/kernel/test/logger_SUITE.erl
+++ b/lib/kernel/test/logger_SUITE.erl
@@ -87,6 +87,7 @@ all() ->
macros,
set_level,
set_module_level,
+ set_application_level,
cache_module_level,
format_report,
filter_failed,
@@ -355,6 +356,7 @@ log_all_levels_api(cleanup,_Config) ->
macros(_Config) ->
ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
test_macros(emergency),
+ test_log_macro(alert),
ok.
macros(cleanup,_Config) ->
@@ -422,6 +424,34 @@ set_module_level(cleanup,_Config) ->
logger:unset_module_level(?MODULE),
ok.
+set_application_level(_Config) ->
+
+ {error,{not_loaded,mnesia}} = logger:set_application_level(mnesia, warning),
+ {error,{not_loaded,mnesia}} = logger:unset_application_level(mnesia),
+
+ application:load(mnesia),
+ {ok, Modules} = application:get_key(mnesia, modules),
+ [] = logger:get_module_level(Modules),
+
+ {error,{invalid_level,warn}} = logger:set_application_level(mnesia, warn),
+
+ ok = logger:set_application_level(mnesia, debug),
+ DebugModules = lists:sort([{M,debug} || M <- Modules]),
+ DebugModules = lists:sort(logger:get_module_level(Modules)),
+
+ ok = logger:set_application_level(mnesia, warning),
+
+ WarnModules = lists:sort([{M,warning} || M <- Modules]),
+ WarnModules = lists:sort(logger:get_module_level(Modules)),
+
+ ok = logger:unset_application_level(mnesia),
+ [] = logger:get_module_level(Modules).
+
+set_application_level(cleanup,_Config) ->
+ ok = logger:unset_application_level(mnesia),
+ ok = application:unload(mnesia),
+ ok.
+
cache_module_level(_Config) ->
ok = logger:unset_module_level(?MODULE),
[] = ets:lookup(?LOGGER_TABLE,?MODULE), %dirty - add API in logger_config?
@@ -469,7 +499,11 @@ filter_failed(_Config) ->
%% Logger filters
{error,{invalid_filter,_}} =
logger:add_primary_filter(lf,{fun(_) -> ok end,args}),
- ok = logger:add_primary_filter(lf,{fun(_,_) -> a=b end,args}),
+ ok = logger:add_primary_filter(lf,
+ {fun(_,_) ->
+ erlang:error({badmatch,b})
+ end,
+ args}),
#{filters:=[_]} = logger:get_primary_config(),
ok = logger:notice(M1=?map_rep),
ok = check_logged(notice,M1,#{}),
@@ -487,7 +521,11 @@ filter_failed(_Config) ->
{error,{not_found,h0}} = logger:remove_handler_filter(h0,hf),
{error,{invalid_filter,_}} =
logger:add_handler_filter(h1,hf,{fun(_) -> ok end,args}),
- ok = logger:add_handler_filter(h1,hf,{fun(_,_) -> a=b end,args}),
+ ok = logger:add_handler_filter(h1,hf,
+ {fun(_,_) ->
+ erlang:error({badmatch,b})
+ end,
+ args}),
{ok,#{filters:=[_]}} = logger:get_handler_config(h1),
ok = logger:notice(M3=?map_rep),
ok = check_logged(notice,M3,#{}),
@@ -523,7 +561,11 @@ handler_failed(_Config) ->
false = lists:search(fun(#{id:=h1}) -> true; (_) -> false end,H1),
{error,{not_found,h1}} = logger:remove_handler(h1),
- ok = logger:add_handler(h2,?MODULE,#{filter_default=>log,log_call=>fun() -> a = b end}),
+ ok = logger:add_handler(h2,?MODULE,
+ #{filter_default => log,
+ log_call => fun() ->
+ erlang:error({badmatch,b})
+ end}),
{error,{already_exist,h2}} = logger:add_handler(h2,othermodule,#{}),
[add] = test_server:messages_get(),
@@ -534,7 +576,7 @@ handler_failed(_Config) ->
{error,{not_found,h2}} = logger:remove_handler(h2),
CallAddHandler = fun() -> logger:add_handler(h2,?MODULE,#{}) end,
- CrashHandler = fun() -> a = b end,
+ CrashHandler = fun() -> erlang:error({badmatch,b}) end,
KillHandler = fun() -> exit(self(), die) end,
{error,{handler_not_added,{attempting_syncronous_call_to_self,_}}} =
@@ -1009,6 +1051,34 @@ test_macros(emergency=Level) ->
[{F2,x},{error,fun_that_crashes}],#{}),
ok.
+test_log_macro(Level) ->
+ ?LOG(Level,#{Level=>rep}),
+ ok = check_logged(Level,#{Level=>rep},?MY_LOC(1)),
+ ?LOG(Level,#{Level=>rep},#{my=>meta}),
+ ok = check_logged(Level,#{Level=>rep},(?MY_LOC(1))#{my=>meta}),
+ ?LOG(Level,"~w: ~w",[Level,fa]),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],?MY_LOC(1)),
+ ?LOG(Level,"~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fa,meta],(?MY_LOC(1))#{my=>meta}),
+ ?LOG(Level,fun(x) -> {"~w: ~w ~w",[Level,fun_to_fa,meta]} end,
+ x, #{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],
+ (?MY_LOC(3))#{my=>meta}),
+ ?LOG(Level,fun(x) -> #{Level=>fun_to_r,meta=>true} end, x, #{my=>meta}),
+ ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},
+ (?MY_LOC(2))#{my=>meta}),
+ ?LOG(Level,fun(x) -> <<"fun_to_s">> end,x,#{}),
+ ok = check_logged(Level,<<"fun_to_s">>,?MY_LOC(1)),
+ F1=fun(x) -> {fun_to_bad} end,
+ ?LOG(Level,F1,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{F1,x},{fun_to_bad}],#{}),
+ F2=fun(x) -> erlang:error(fun_that_crashes) end,
+ ?LOG(Level,F2,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{F2,x},{error,fun_that_crashes}],#{}),
+ ok.
+
%%%-----------------------------------------------------------------
%%% Called by macro ?TRY(X)
my_try(Fun) ->
diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl
index 7e5b574869..a4b15c841b 100644
--- a/lib/kernel/test/logger_disk_log_h_SUITE.erl
+++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl
@@ -1551,25 +1551,30 @@ h_proc_name() ->
h_proc_name(Name) ->
list_to_atom(lists:concat([logger_disk_log_h,"_",Name])).
-file_delete(Log) ->
- file:delete(Log).
-
wait_for_process_up(T) ->
- wait_for_process_up(h_proc_name(),T).
+ wait_for_process_up(?MODULE, h_proc_name(), T).
-wait_for_process_up(Name,T) ->
+wait_for_process_up(Name, RegName, T) ->
N = (T div 500) + 1,
- wait_for_process_up1(Name,N).
+ wait_for_process_up1(Name, RegName, N).
-wait_for_process_up1(Name,0) ->
+wait_for_process_up1(_Name, _RegName, 0) ->
error;
-wait_for_process_up1(Name,N) ->
+wait_for_process_up1(Name, RegName, N) ->
timer:sleep(500),
- case whereis(Name) of
+ case whereis(RegName) of
Pid when is_pid(Pid) ->
- %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
- {ok,Pid};
+ case logger:get_handler_config(Name) of
+ {ok,_} ->
+ %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
+ {ok,Pid};
+ _ ->
+ wait_for_process_up1(Name, RegName, N-1)
+ end;
undefined ->
%% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]),
- wait_for_process_up1(Name,N-1)
+ wait_for_process_up1(Name, RegName, N-1)
end.
+
+file_delete(Log) ->
+ file:delete(Log).
diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl
index 04a4364947..e8d1a313dc 100644
--- a/lib/kernel/test/logger_env_var_SUITE.erl
+++ b/lib/kernel/test/logger_env_var_SUITE.erl
@@ -71,6 +71,7 @@ all() ->
sasl_compatible_false,
sasl_compatible_false_no_progress,
sasl_compatible,
+ all_logger_level,
{group,bad},
{group,error_logger},
{group,logger}
@@ -572,6 +573,24 @@ sasl_compatible(Config) ->
0),% progress in std logger
ok.
+all_logger_level(Config) ->
+ [all_logger_level(Config,Level) || Level <- [none,
+ emergency,
+ alert,
+ critical,
+ error,
+ warning,
+ notice,
+ info,
+ debug,
+ all]],
+ ok.
+
+all_logger_level(Config,Level) ->
+ {ok,#{primary:=#{level:=Level}},Node} = setup(Config,[{logger_level,Level}]),
+ true = test_server:stop_node(Node),
+ ok.
+
bad_error_logger(Config) ->
error = setup(Config,[{error_logger,baddest}]).
diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl
index 8fe8d5199b..2ec4b243cf 100644
--- a/lib/kernel/test/logger_formatter_SUITE.erl
+++ b/lib/kernel/test/logger_formatter_SUITE.erl
@@ -166,6 +166,56 @@ single_line(_Config) ->
" info:\nterm\n" = string:prefix(String2,ExpectedTimestamp),
String2 = format(info,{"~p",[term]},#{time=>Time},#{single_line=>bad}),
+
+
+ %% Test that no extra commas/spaces are added when removing
+ %% newlines, especially not after "=>" in a map association (as
+ %% was the case in OTP-21.0, when the only single_line adjustment
+ %% was done by regexp replacement of "\n" by ", ").
+ Prefix =
+ "Some characters to fill the line ------------------------------------- ",
+ String3 = format(info,{"~s~p~n~s~p~n",[Prefix,
+ lists:seq(1,10),
+ Prefix,
+ #{a=>map,with=>a,few=>accociations}]},
+ #{time=>Time},
+ #{single_line=>true}),
+ ct:log(String3),
+ match = re:run(String3,"\\[1,2,3,4,5,6,7,8,9,10\\]",[{capture,none}]),
+ match = re:run(String3,
+ "#{a => map,few => accociations,with => a}",
+ [{capture,none}]),
+
+ %% This part is added to make sure that the previous test made
+ %% sense, i.e. that there would actually be newlines inside the
+ %% list and map.
+ String4 = format(info,{"~s~p~n~s~p~n",[Prefix,
+ lists:seq(1,10),
+ Prefix,
+ #{a=>map,with=>a,few=>accociations}]},
+ #{time=>Time},
+ #{single_line=>false}),
+ ct:log(String4),
+ match = re:run(String4,"\\[1,2,3,\n",[global,{capture,none}]),
+ {match,Match4} = re:run(String4,"=>\n",[global,{capture,all}]),
+ 3 = length(Match4),
+
+ %% Test that big metadata fields do not get line breaks
+ String5 = format(info,"",
+ #{mymeta=>lists:seq(1,100)},
+ #{single_line=>true,template=>[mymeta,"\n"]}),
+ ct:log(String5),
+ [_] = string:lexemes(String5,"\n"),
+
+ %% Ensure that the previous test made sense, i.e. that the
+ %% metadata field does produce multiple lines if
+ %% single_line==false.
+ String6 = format(info,"",
+ #{mymeta=>lists:seq(1,100)},
+ #{single_line=>false,template=>[mymeta,"\n"]}),
+ ct:log(String6),
+ [_,_|_] = string:lexemes(String6,"\n"),
+
ok.
template(_Config) ->
@@ -312,30 +362,48 @@ format_msg(_Config) ->
#{report_cb=>fun(_)-> faulty_return end},
#{template=>Template}),
ct:log(String5),
- "REPORT_CB ERROR: term; Returned: faulty_return" = String5,
+ "REPORT_CB/1 ERROR: term; Returned: faulty_return" = String5,
String6 = format(info,{report,term},
#{report_cb=>fun(_)-> erlang:error(fun_crashed) end},
#{template=>Template}),
ct:log(String6),
- "REPORT_CB CRASH: term; Reason: {error,fun_crashed}" = String6,
+ "REPORT_CB/1 CRASH: term; Reason: {error,fun_crashed,"++_ = String6,
+
+ String7 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> ['not',a,string] end},
+ #{template=>Template}),
+ ct:log(String7),
+ "REPORT_CB/2 ERROR: term; Returned: ['not',a,string]" = String7,
+
+ String8 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> faulty_return end},
+ #{template=>Template}),
+ ct:log(String8),
+ "REPORT_CB/2 ERROR: term; Returned: faulty_return" = String8,
+
+ String9 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> erlang:error(fun_crashed) end},
+ #{template=>Template}),
+ ct:log(String9),
+ "REPORT_CB/2 CRASH: term; Reason: {error,fun_crashed,"++_ = String9,
%% strings are not formatted
- String7 = format(info,{string,"string"},
+ String10 = format(info,{string,"string"},
#{report_cb=>fun(_)-> {"formatted",[]} end},
#{template=>Template}),
- ct:log(String7),
- "string" = String7,
+ ct:log(String10),
+ "string" = String10,
- String8 = format(info,{string,['not',printable,list]},
+ String11 = format(info,{string,['not',printable,list]},
#{report_cb=>fun(_)-> {"formatted",[]} end},
#{template=>Template}),
- ct:log("~ts",[String8]), % avoiding ct_log crash
- "FORMAT ERROR: \"~ts\" - [['not',printable,list]]" = String8,
+ ct:log("~ts",[String11]), % avoiding ct_log crash
+ "FORMAT ERROR: \"~ts\" - [['not',printable,list]]" = String11,
- String9 = format(info,{string,"string"},#{},#{template=>Template}),
- ct:log(String9),
- "string" = String9,
+ String12 = format(info,{string,"string"},#{},#{template=>Template}),
+ ct:log(String12),
+ "string" = String12,
ok.
@@ -639,8 +707,10 @@ check_config(_Config) ->
?cfgerr({max_size,bad}) =
logger_formatter:check_config(#{max_size => bad}),
+ ok =
+ logger_formatter:check_config(#{report_cb => fun(_,_) -> "" end}),
?cfgerr({report_cb,F}) =
- logger_formatter:check_config(#{report_cb => F=fun(_,_) -> {"",[]} end}),
+ logger_formatter:check_config(#{report_cb => F=fun(_,_,_) -> {"",[]} end}),
?cfgerr({report_cb,bad}) =
logger_formatter:check_config(#{report_cb => bad}),
diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl
index ca54458ac1..0930cd4211 100644
--- a/lib/kernel/test/logger_std_h_SUITE.erl
+++ b/lib/kernel/test/logger_std_h_SUITE.erl
@@ -1570,27 +1570,29 @@ h_proc_name() ->
h_proc_name(Name) ->
?name_to_reg_name(logger_std_h,Name).
-file_delete(Log) ->
- file:delete(Log).
-
wait_for_process_up(T) ->
- wait_for_process_up(h_proc_name(),T).
+ wait_for_process_up(?MODULE, h_proc_name(), T).
-wait_for_process_up(Name,T) ->
+wait_for_process_up(Name, RegName, T) ->
N = (T div 500) + 1,
- wait_for_process_up1(Name,N).
+ wait_for_process_up1(Name, RegName, N).
-wait_for_process_up1(_Name,0) ->
+wait_for_process_up1(_Name, _RegName, 0) ->
error;
-wait_for_process_up1(Name,N) ->
+wait_for_process_up1(Name, RegName, N) ->
timer:sleep(500),
- case whereis(Name) of
+ case whereis(RegName) of
Pid when is_pid(Pid) ->
- %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
- {ok,Pid};
+ case logger:get_handler_config(Name) of
+ {ok,_} ->
+ %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
+ {ok,Pid};
+ _ ->
+ wait_for_process_up1(Name, RegName, N-1)
+ end;
undefined ->
%% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]),
- wait_for_process_up1(Name,N-1)
+ wait_for_process_up1(Name, RegName, N-1)
end.
filesync_rep_int() ->
@@ -1598,3 +1600,8 @@ filesync_rep_int() ->
true -> 5500;
false -> ?FILESYNC_REPEAT_INTERVAL + 500
end.
+
+
+file_delete(Log) ->
+ file:delete(Log).
+
diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl
index ceb4e9cc49..cf4bf11328 100644
--- a/lib/kernel/test/seq_trace_SUITE.erl
+++ b/lib/kernel/test/seq_trace_SUITE.erl
@@ -783,6 +783,24 @@ do_shrink(N) ->
erlang:garbage_collect(),
do_shrink(N-1).
+%% Test that messages from a port does not clear the token
+port_clean_token(Config) when is_list(Config) ->
+ seq_trace:reset_trace(),
+ Label = make_ref(),
+ seq_trace:set_token(label, Label),
+ {label,Label} = seq_trace:get_token(label),
+
+ %% Create a port and get messages from it
+ %% We use os:cmd as a convenience as it does
+ %% open_port, port_command, port_close and receives replies.
+ %% Maybe it is not ideal to rely on the internal implementation
+ %% of os:cmd but it will have to do.
+ os:cmd("ls"),
+
+ %% Make sure that the seq_trace token is still there
+ {label,Label} = seq_trace:get_token(label),
+
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/megaco/doc/src/Makefile b/lib/megaco/doc/src/Makefile
index 43704cddf4..72feb9d2b3 100644
--- a/lib/megaco/doc/src/Makefile
+++ b/lib/megaco/doc/src/Makefile
@@ -114,6 +114,7 @@ clean_man:
clean_html:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
imgs: $(IMG_FILES:%=$(HTMLDIR)/%)
diff --git a/lib/mnesia/doc/src/Makefile b/lib/mnesia/doc/src/Makefile
index da52c69f00..d9647fc081 100644
--- a/lib/mnesia/doc/src/Makefile
+++ b/lib/mnesia/doc/src/Makefile
@@ -118,6 +118,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 51b32129b6..2fae542c86 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -130,7 +130,7 @@
<name>key_to_frag_number(State, Key) -> FragNum | abort(Reason)</name>
<fsummary>Resolves the key of a record into a fragment number.</fsummary>
<type>
- <v>FragNum = integer()()</v>
+ <v>FragNum = integer()</v>
<v>Reason = term()</v>
</type>
<desc>
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 7134e3d1e4..8a7dab739e 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -54,6 +54,32 @@
</section>
+<section><title>Mnesia 4.15.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When master node is set do not force a load from
+ ram_copies replica when there are no available
+ disc_copies, since that would load an empty table. Wait
+ until a disk replica is available or until user
+ explicitly force_loads the table.</p>
+ <p>
+ Own Id: OTP-15221 Aux Id: ERIERL-217 </p>
+ </item>
+ <item>
+ <p>
+ Allow to add replicas even if all other replicas are down
+ when the other replicase are not stored on disk.</p>
+ <p>
+ Own Id: OTP-15226 Aux Id: ERIERL-221 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Mnesia 4.15.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -663,7 +689,7 @@
<p>
Returns the same value for
mnesia_loader:disc_load_table/2 as
- mnesia_loader:net_load_table/4 if a table copy can not be
+ mnesia_loader:net_load_table/4 if a table copy cannot be
found. (Thanks to Uwe Dauernheim)</p>
<p>
Own Id: OTP-10015</p>
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index e298904e2a..223dba3f90 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -168,6 +168,9 @@
-type snmp_struct() :: [{atom(), snmp_type() | tuple_of(snmp_type())}].
-type snmp_type() :: 'fix_string' | 'string' | 'integer'.
-type tuple_of(_T) :: tuple().
+-type config_key() :: extra_db_nodes | dc_dump_limit.
+-type config_value() :: [node()] | number().
+-type config_result() :: {ok, config_value()} | {error, term()}.
-define(DEFAULT_ACCESS, ?MODULE).
@@ -278,7 +281,8 @@ stop() ->
Other -> Other
end.
--spec change_config(Config::atom(), Value::_) -> ok | {error, term()}.
+-spec change_config(Config::config_key(), Value::config_value()) ->
+ config_result().
change_config(extra_db_nodes, Ns) when is_list(Ns) ->
mnesia_controller:connect_nodes(Ns);
change_config(dc_dump_limit, N) when is_number(N), N > 0 ->
@@ -779,12 +783,16 @@ do_delete_object(Tid, Ts, Tab, Val, LockKind) ->
?ets_insert(Store, {Oid, Val, delete_object});
_ ->
case ?ets_match_object(Store, {Oid, '_', write}) of
- [] ->
- ?ets_match_delete(Store, {Oid, Val, '_'}),
- ?ets_insert(Store, {Oid, Val, delete_object});
- _ ->
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Oid, delete})
+ [] ->
+ ?ets_match_delete(Store, {Oid, Val, '_'}),
+ ?ets_insert(Store, {Oid, Val, delete_object});
+ Ops ->
+ case lists:member({Oid, Val, write}, Ops) of
+ true ->
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Oid, delete});
+ false -> ok
+ end
end
end,
ok;
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index f81ba783f2..882de0d613 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -772,22 +772,6 @@ handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
end;
-handle_call({net_load, Tab, Cs}, From, State) ->
- State2 =
- case State#state.schema_is_merged of
- true ->
- Worker = #net_load{table = Tab,
- opt_reply_to = From,
- reason = {dumper,{add_table_copy, unknown}},
- cstruct = Cs
- },
- add_worker(Worker, State);
- false ->
- reply(From, {not_loaded, schema_not_merged}),
- State
- end,
- noreply(State2);
-
handle_call(Msg, From, State) when State#state.schema_is_merged /= true ->
%% Buffer early messages
Msgs = State#state.early_msgs,
@@ -1457,7 +1441,8 @@ orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
L = [Tab | Local],
orphan_tables(Tabs, Node, Ns, L, Remote);
Masters ->
- R = [{Tab, Masters} | Remote],
+ %% Do not disc_load table from RamCopyHolders
+ R = [{Tab, Masters -- RamCopyHolders} | Remote],
orphan_tables(Tabs, Node, Ns, Local, R)
end;
_ ->
@@ -2162,6 +2147,15 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl
{dumper,{add_table_copy,_}} -> true;
_ -> false
end,
+
+ OnlyRamCopies = case Cs of
+ #cstruct{disc_copies = DC,
+ disc_only_copies = DOC,
+ external_copies = Ext} ->
+ [] =:= (DC ++ (DOC ++ Ext)) -- [node()];
+ _ ->
+ false
+ end,
if
ReadNode == node() ->
%% Already loaded locally
@@ -2173,6 +2167,8 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl
end;
AccessMode == read_only, not AddTableCopy ->
fun() -> disc_load_table(Tab, Reason, ReplyTo) end;
+ Active =:= [], AddTableCopy, OnlyRamCopies ->
+ fun() -> disc_load_table(Tab, Reason, ReplyTo) end;
true ->
fun() ->
%% Either we cannot read the table yet
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index a884b8e086..6abc05fade 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -929,7 +929,7 @@ error_desc(no_transaction) -> "Operation not allowed outside transactions";
error_desc(combine_error) -> "Table options were ilegally combined";
error_desc(bad_index) -> "Index already exists or was out of bounds";
error_desc(already_exists) -> "Some schema option we try to set is already on";
-error_desc(index_exists)-> "Some ops can not be performed on tabs with index";
+error_desc(index_exists)-> "Some ops cannot be performed on tabs with index";
error_desc(no_exists)-> "Tried to perform op on non-existing (non alive) item";
error_desc(system_limit) -> "Some system_limit was exhausted";
error_desc(mnesia_down) -> "A transaction involving objects at some remote "
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index ebe924a86e..2cdae0c906 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -67,7 +67,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
EtsOpts = proplists:get_value(ets, StorageProps, []),
Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources already allocated
+ {dumper, DR} when is_atom(DR) -> %% Resources already allocated
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
@@ -91,8 +91,8 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
EtsOpts = proplists:get_value(ets, StorageProps, []),
Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources allready allocated
- ignore;
+ {dumper, DR} when is_atom(DR) ->
+ ignore; %% Resources already allocated
_ ->
mnesia_monitor:mktab(Tab, Args),
Fname = mnesia_lib:tab2dcd(Tab),
@@ -131,7 +131,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
{repair, mnesia_monitor:get_env(auto_repair)}
| DetsOpts],
case Reason of
- {dumper, _} ->
+ {dumper, DR} when is_atom(DR) ->
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
set({Tab, load_node}, node()),
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index 4b3fffc735..cbf7db28f0 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -1661,7 +1661,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
?eval_debug_fun({?MODULE, commit_participant, pre}, [{tid, Tid}]),
try mnesia_schema:prepare_commit(Tid, C0, {part, Coord}) of
{Modified, C = #commit{}, DumperMode} ->
- %% If we can not find any local unclear decision
+ %% If we cannot find any local unclear decision
%% we should presume abort at startup recovery
case lists:member(node(), DiscNs) of
false ->
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl
index 62199d8b9a..ccbfdc9738 100644
--- a/lib/mnesia/test/mnesia_durability_test.erl
+++ b/lib/mnesia/test/mnesia_durability_test.erl
@@ -46,6 +46,7 @@
master_nodes/1, starting_master_nodes/1,
master_on_non_local_tables/1,
remote_force_load_with_local_master_node/1,
+ master_node_with_ram_copy_2/1, master_node_with_ram_copy_3/1,
dump_ram_copies/1, dump_disc_copies/1, dump_disc_only/1]).
-include("mnesia_test_lib.hrl").
@@ -91,7 +92,8 @@ groups() ->
{load_tables_with_master_tables, [],
[master_nodes, starting_master_nodes,
master_on_non_local_tables,
- remote_force_load_with_local_master_node]},
+ remote_force_load_with_local_master_node,
+ master_node_with_ram_copy_2, master_node_with_ram_copy_3]},
{durability_of_dump_tables, [],
[dump_ram_copies, dump_disc_copies, dump_disc_only]}].
@@ -1165,6 +1167,107 @@ remote_force_load_with_local_master_node(Config) when is_list(Config) ->
?verify_mnesia(Nodes, []).
+master_node_with_ram_copy_2(Config) when is_list(Config) ->
+ [A, B] = Nodes = ?acquire_nodes(2, Config),
+ Tab = ?FUNCTION_NAME,
+ ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A]}, {ram_copies, [B]}])),
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+
+ %% Test that we don't load from ram_copies
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node require force_load
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+
+ ?match(yes, rpc:call(A, mnesia, force_load_table, [Tab])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+
+ ?verify_mnesia(Nodes, []).
+
+
+master_node_with_ram_copy_3(Config) when is_list(Config) ->
+ [A, B, C] = Nodes = ?acquire_nodes(3, Config),
+ Tab = ?FUNCTION_NAME,
+ ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A,C]}, {ram_copies, [B]}])),
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+
+ %% Test that we don't load from ram_copies
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node will wait until loaded
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node requires force load
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(ok, rpc:call(C, mnesia, set_master_nodes, [[B]])),
+
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(yes, rpc:call(C, mnesia, force_load_table, [Tab])),
+
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(C, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ ?verify_mnesia(Nodes, []).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1415,7 +1518,7 @@ do_disc_durability(Config,CopyType) ->
[{Tab_bag, 22, a_2222}], [{Tab_bag, 33, a_3333}],
[{Tab_set, counter, 10}]]),
- timer:sleep(1000), %% Debugging strange msgs..
+ timer:sleep(500), %% Debugging strange msgs..
?log("Flushed ~p ~n", [mnesia_test_lib:flush()]),
?verify_mnesia(Nodes, []).
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index eb1f987cf0..77236940d4 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -31,6 +31,7 @@
db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1,
checkpoint/1, table_lifecycle/1, storage_options/1,
add_copy_conflict/1, add_copy_when_going_down/1,
+ add_copy_with_down/1,
replica_management/1, clear_table_during_load/1,
schema_availability/1, local_content/1,
replica_location/1, user_properties/1, unsupp_user_props/1,
@@ -65,7 +66,8 @@ all() ->
db_node_lifecycle, evil_delete_db_node, start_and_stop,
checkpoint, table_lifecycle, storage_options,
add_copy_conflict,
- add_copy_when_going_down, replica_management, clear_table_during_load,
+ add_copy_when_going_down, add_copy_with_down, replica_management,
+ clear_table_during_load,
schema_availability, local_content,
{group, table_access_modifications}, replica_location,
{group, table_sync}, user_properties, unsupp_user_props,
@@ -732,6 +734,49 @@ add_copy_when_going_down(Config) ->
?match_receive({test,{aborted,_}}),
?verify_mnesia([Node2], []).
+add_copy_with_down(suite) -> [];
+add_copy_with_down(Config) ->
+ %% Allow add_table_copy() with ram_copies even all other replicas are down
+ Nodes = [Node1, Node2, Node3] = ?acquire_nodes(3, Config),
+ ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node3]}, {disc_copies, [Node2]}])),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match({aborted, _}, mnesia:del_table_copy(a, Node2)),
+ ok = rpc:call(Node3, mnesia, start, []),
+ ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match([], mnesia_test_lib:start_mnesia([Node2], [a])),
+ ?match({atomic, ok}, mnesia:change_table_copy_type(a, Node2, ram_copies)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_only_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?verify_mnesia(Nodes, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Add, drop and move replicas, change storage types
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index b2eea2390b..49bcec14af 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -1563,7 +1563,8 @@ trans_update_visible_inside_trans(Config) when is_list(Config) ->
?match({atomic, ok}, mnesia:create_table([{name, Tab},
{ram_copies, [Node1]}])),
ValPos = 3,
- RecA = {Tab, a, 1},
+ RecA = {Tab, a, 1},
+ RecA2 = {Tab, a, 2},
PatA = {Tab, '$1', 1},
RecB = {Tab, b, 3},
PatB = {Tab, '$1', 3},
@@ -1598,6 +1599,14 @@ trans_update_visible_inside_trans(Config) when is_list(Config) ->
?match([], mnesia:index_read(Tab, 3, ValPos)),
%% delete_object
+ ?match(ok, mnesia:delete_object(RecA2)),
+ ?match([RecA], mnesia:read({Tab, a})),
+ ?match([RecA], mnesia:wread({Tab, a})),
+ ?match([RecA], mnesia:match_object(PatA)),
+ ?match([a], mnesia:all_keys(Tab)),
+ ?match([RecA], mnesia:index_match_object(PatA, ValPos)),
+ ?match([RecA], mnesia:index_read(Tab, 1, ValPos)),
+
?match(ok, mnesia:delete_object(RecA)),
?match([], mnesia:read({Tab, a})),
?match([], mnesia:wread({Tab, a})),
diff --git a/lib/observer/doc/src/Makefile b/lib/observer/doc/src/Makefile
index 11bfee1bdb..e843772f0b 100644
--- a/lib/observer/doc/src/Makefile
+++ b/lib/observer/doc/src/Makefile
@@ -105,6 +105,7 @@ html: gifs $(HTML_REF_MAN_FILE) $(ONLY_HTML_FILE:%=$(HTMLDIR)/%)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
diff --git a/lib/observer/src/cdv_bin_cb.erl b/lib/observer/src/cdv_bin_cb.erl
index a4a542297c..91d33474c8 100644
--- a/lib/observer/src/cdv_bin_cb.erl
+++ b/lib/observer/src/cdv_bin_cb.erl
@@ -49,7 +49,7 @@ format_bin_fun(Format,Bin) ->
try io_lib:format(Format,[Bin]) of
Str -> plain_html(lists:flatten(Str))
catch error:badarg ->
- Warning = "This binary can not be formatted with " ++ Format,
+ Warning = "This binary cannot be formatted with " ++ Format,
observer_html_lib:warning(Warning)
end
end.
@@ -59,7 +59,7 @@ binary_to_term_fun(Bin) ->
try binary_to_term(Bin) of
Term -> plain_html(io_lib:format("~tp",[Term]))
catch error:badarg ->
- Warning = "This binary can not be converted to an Erlang term",
+ Warning = "This binary cannot be converted to an Erlang term",
observer_html_lib:warning(Warning)
end
end.
diff --git a/lib/observer/src/cdv_term_cb.erl b/lib/observer/src/cdv_term_cb.erl
index 91de6449c4..85da1d227a 100644
--- a/lib/observer/src/cdv_term_cb.erl
+++ b/lib/observer/src/cdv_term_cb.erl
@@ -51,7 +51,7 @@ format_term_fun(Format,Term,Tab) ->
try io_lib:format(Format,[Term]) of
Str -> {expand, plain_html(Str), Tab}
catch error:badarg ->
- Warning = "This term can not be formatted with " ++ Format,
+ Warning = "This term cannot be formatted with " ++ Format,
observer_html_lib:warning(Warning)
after
observer_lib:report_progress({ok,stop_pulse})
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index 814f3a1260..dfd19569fd 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -147,7 +147,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_activated,
State=#state{holder=Holder, node=Node, opts=#opts{type=Type}, grid=Grid}) ->
case get_table(Holder, Index) of
#tab{protection=private} ->
- self() ! {error, "Table has 'private' protection and can not be read"};
+ self() ! {error, "Table has 'private' protection and cannot be read"};
#tab{}=Table ->
observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}]);
_ -> ignore
@@ -187,7 +187,7 @@ handle_event(#wx{id=?ID_SHOW_TABLE},
R when is_integer(R) ->
case get_table(Holder, R) of
#tab{protection=private} ->
- self() ! {error, "Table has 'private' protection and can not be read"};
+ self() ! {error, "Table has 'private' protection and cannot be read"};
#tab{}=Table ->
observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}]);
_ -> ignore
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 453e3bdc2d..1f748cb8d2 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -806,7 +806,7 @@ is_rb_compatible(Node) ->
is_rb_server_running(Node, LogState) ->
%% If already started, somebody else may use it.
- %% We can not use it too, as far log file would be overriden. Not fair.
+ %% We cannot use it too, as far log file would be overriden. Not fair.
case rpc:block_call(Node, erlang, whereis, [rb_server]) of
Pid when is_pid(Pid), (LogState == false) ->
throw("Error: rb_server is already started and maybe used by someone.");
diff --git a/lib/observer/test/crashdump_viewer_SUITE_data/old_format.dump b/lib/observer/test/crashdump_viewer_SUITE_data/old_format.dump
index 2c8944fa9d..2737757bfa 100644
--- a/lib/observer/test/crashdump_viewer_SUITE_data/old_format.dump
+++ b/lib/observer/test/crashdump_viewer_SUITE_data/old_format.dump
@@ -1285,7 +1285,7 @@ sleep
start_prim_loader
erl_prim_loader
set_path
-'can not start loader'
+'cannot start loader'
add_to_kernel
prim_load_flags
'-loader'
@@ -1304,7 +1304,7 @@ path_flags
'-pz'
get_boot
not_found
-'can not get bootfile'
+'cannot get bootfile'
'bootfile format error'
get_file
script
@@ -1349,7 +1349,7 @@ extension
'-boot/1-fun-0-'
'-bs2ss/1-fun-0-'
'-bs2as/1-fun-0-'
-'can not load'
+'cannot load'
'unexpected command in bootfile'
prim_inet
open
@@ -3071,7 +3071,7 @@ change_group
change_time
master
start_slave
-'can not get remote filer '
+'cannot get remote filer '
start_relay
relay
'Port controlling ~w terminated in file_server'
diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl
index 40f5d44847..75336cedcc 100644
--- a/lib/observer/test/observer_SUITE.erl
+++ b/lib/observer/test/observer_SUITE.erl
@@ -301,7 +301,7 @@ table_win(Config) when is_list(Config) ->
Notebook = setup_whitebox_testing(),
Parent = get_top_level_parent(Notebook),
TObj = observer_tv_table:start_link(Parent, [{node,node()}, {type,ets}, {table,#tab{name=foo, id=Table}}]),
- %% Modal can not test edit..
+ %% Modal cannot test edit..
%% TPid = wx_object:get_pid(TObj),
%% TPid ! #wx{event=#wxList{type=command_list_item_activated, itemIndex=12}},
timer:sleep(3000),
diff --git a/lib/odbc/doc/src/Makefile b/lib/odbc/doc/src/Makefile
index b3f93a7e9c..553db8a9a4 100644
--- a/lib/odbc/doc/src/Makefile
+++ b/lib/odbc/doc/src/Makefile
@@ -101,6 +101,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/odbc/doc/src/databases.xml b/lib/odbc/doc/src/databases.xml
index a060f87e46..614c327a46 100644
--- a/lib/odbc/doc/src/databases.xml
+++ b/lib/odbc/doc/src/databases.xml
@@ -65,7 +65,7 @@
<p>Another obstacle is that some drivers do not support scrollable
cursors which has the effect that the only way to traverse the
result set is sequentially, with next, from the first row to the
- last, and once you pass a row you can not go back. This means
+ last, and once you pass a row you cannot go back. This means
that some functions in the interface will not work together with
certain drivers. A similar problem is that not all drivers
support "row count" for select queries, hence resulting in that
diff --git a/lib/odbc/doc/src/error_handling.xml b/lib/odbc/doc/src/error_handling.xml
index 4c80cff12f..8d794d2c99 100644
--- a/lib/odbc/doc/src/error_handling.xml
+++ b/lib/odbc/doc/src/error_handling.xml
@@ -138,7 +138,7 @@
should be run through the erlang port was not compiled for
your platform.</item>
<item>Errors discovered by the ODBC driver - If calls to the
- ODBC-driver fails due to circumstances that can not be
+ ODBC-driver fails due to circumstances that cannot be
controlled by the Erlang ODBC application programmer, an
error string will be dug up from the driver. This string
will be the <c>Reason</c> in the <c>{error, Reason} </c>
diff --git a/lib/odbc/doc/src/getting_started.xml b/lib/odbc/doc/src/getting_started.xml
index f2ff8b8993..b27754ff22 100644
--- a/lib/odbc/doc/src/getting_started.xml
+++ b/lib/odbc/doc/src/getting_started.xml
@@ -50,7 +50,7 @@
and paths to appropriate values. This may differ a lot
between different os's, databases and ODBC drivers. This
is a configuration problem related to the third party product
- and hence we can not give you a standard solution in this guide.</item>
+ and hence we cannot give you a standard solution in this guide.</item>
<item>The Erlang ODBC application consists of both <c>Erlang</c>
and <c>C</c> code. The <c>C</c> code is delivered as a
precompiled executable for windows, solaris and linux (SLES10) in the commercial
diff --git a/lib/odbc/doc/src/notes_history.xml b/lib/odbc/doc/src/notes_history.xml
index 22a92f67cd..d0c0a472e7 100644
--- a/lib/odbc/doc/src/notes_history.xml
+++ b/lib/odbc/doc/src/notes_history.xml
@@ -63,7 +63,7 @@
<list type="bulleted">
<item>
<p>The erlang odbc process will now die normally if a
- connection can not be established. No connection no
+ connection cannot be established. No connection no
process it is expected. And as the client has already
received the error message that would be the reason with
which the erlang process would be stopped, the supervisor
@@ -193,7 +193,7 @@
</item>
<item>
<p>The erlang odbc process will now die normally if a
- connection can not be established. No connection no
+ connection cannot be established. No connection no
process it is expected. And as the client has already
received the error message that would be the reason with
which the erlang process would be stopped, the supervisor
diff --git a/lib/odbc/doc/src/odbc.xml b/lib/odbc/doc/src/odbc.xml
index 4bb1f035f9..9760908855 100644
--- a/lib/odbc/doc/src/odbc.xml
+++ b/lib/odbc/doc/src/odbc.xml
@@ -246,7 +246,7 @@
<p>Closes a connection to a database. This will also
terminate all processes that may have been spawned
when the connection was opened. This call will always succeed.
- If the connection can not be disconnected gracefully it will
+ If the connection cannot be disconnected gracefully it will
be brutally killed. However you may receive an error message
as result if you try to disconnect a connection started by another
process.
diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl
index 261dfc6f20..94ca62b3fb 100644
--- a/lib/odbc/test/odbc_connect_SUITE.erl
+++ b/lib/odbc/test/odbc_connect_SUITE.erl
@@ -259,7 +259,7 @@ not_exist_db(_Config) ->
%%-------------------------------------------------------------------------
no_c_executable() ->
- [{doc,"Test what happens if the port-program can not be found"}].
+ [{doc,"Test what happens if the port-program cannot be found"}].
no_c_executable(_Config) ->
process_flag(trap_exit, true),
Dir = filename:nativename(filename:join(code:priv_dir(odbc),
diff --git a/lib/os_mon/doc/src/Makefile b/lib/os_mon/doc/src/Makefile
index 4aa8879a91..354f8ed26b 100644
--- a/lib/os_mon/doc/src/Makefile
+++ b/lib/os_mon/doc/src/Makefile
@@ -98,6 +98,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
index 7122d23503..ba28f31f26 100644
--- a/lib/os_mon/test/cpu_sup_SUITE.erl
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -122,19 +122,19 @@ util_api(Config) when is_list(Config) ->
%% util([])
{all, Busy1, NonBusy1, []} = cpu_sup:util([]),
- 100.00 = Busy1 + NonBusy1,
+ true = tiny_diff(100.00, Busy1 + NonBusy1),
%% util([detailed])
{Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]),
true = lists:all(fun(X) -> is_integer(X) end, Cpus2),
true = lists:all(BusyP, Busy2),
true = lists:all(NonBusyP, NonBusy2),
- 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2),
+ true = tiny_diff(100.00, lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2)),
%% util([per_cpu])
[{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]),
true = is_integer(Cpu3),
- 100.00 = Busy3 + NonBusy3,
+ true = tiny_diff(100.00, Busy3 + NonBusy3),
%% util([detailed, per_cpu])
[{Cpu4, Busy4, NonBusy4, []}|_] =
@@ -142,7 +142,7 @@ util_api(Config) when is_list(Config) ->
true = is_integer(Cpu4),
true = lists:all(BusyP, Busy2),
true = lists:all(NonBusyP, NonBusy2),
- 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4),
+ true = tiny_diff(100.00, lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4)),
%% bad util/1 calls
{'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)),
@@ -150,6 +150,9 @@ util_api(Config) when is_list(Config) ->
ok.
+tiny_diff(A, B) ->
+ (abs(A - B) < 1.0e-11).
+
-define(SPIN_TIME, 1000).
%% Test utilization values
diff --git a/lib/otp_mibs/doc/src/Makefile b/lib/otp_mibs/doc/src/Makefile
index c65e2a8e3c..143d9befb8 100644
--- a/lib/otp_mibs/doc/src/Makefile
+++ b/lib/otp_mibs/doc/src/Makefile
@@ -93,6 +93,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/parsetools/doc/src/Makefile b/lib/parsetools/doc/src/Makefile
index e4cd2c0a76..a40ccd0fe7 100644
--- a/lib/parsetools/doc/src/Makefile
+++ b/lib/parsetools/doc/src/Makefile
@@ -89,6 +89,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index f5157fe87a..03467e9783 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -99,6 +99,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 29e281922c..204520473a 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -35,6 +35,26 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Some of the keylengths in the newly generated moduli file
+ in public_key are not universally supported. This could
+ cause the SSH key exchange
+ diffie-hellman-group-exchange-sha* to fail.</p>
+ <p>
+ Those keylengths are now removed.</p>
+ <p>
+ Own Id: OTP-15151 Aux Id: OTP-15113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index c0a67c25b8..aaccb5088b 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -682,7 +682,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<tag>{undetermined_details, boolean()}</tag>
<item>
- <p>Defaults to false. When revocation status can not be
+ <p>Defaults to false. When revocation status cannot be
determined, and this option is set to true, details of why no
CRLs where accepted are included in the return value.</p>
</item>
@@ -902,7 +902,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<note><p>
Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain
- and they can not be used to achieve real security. This function is provided for testing purposes only.
+ and they cannot be used to achieve real security. This function is provided for testing purposes only.
</p></note>
</desc>
</func>
diff --git a/lib/public_key/priv/moduli b/lib/public_key/priv/moduli
index 0c44d525ba..83e8767a5e 100644
--- a/lib/public_key/priv/moduli
+++ b/lib/public_key/priv/moduli
@@ -172,40 +172,6 @@
20180605201507 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F737264DFF
20180605201935 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F737F47113
20180605202538 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7390F0743
-20180605210627 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFBDE9C663
-20180605211229 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFBE5D31FF
-20180605212615 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFBF726B37
-20180605213758 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC05E3C97
-20180605214634 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC108344F
-20180605221135 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC2F6C7EF
-20180605221612 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC34A2373
-20180605222719 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC426CF47
-20180605225054 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC5FF2A63
-20180605230438 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC70EA13F
-20180605232516 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFC8A507BF
-20180606000440 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCBB897D3
-20180606003911 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCE5E6DDF
-20180606004021 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCE6D003B
-20180606004054 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFCE6EF7C3
-20180606011249 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD0E6DF43
-20180606013848 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD2E87873
-20180606020718 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD5166B47
-20180606021121 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD55F3E2B
-20180606030823 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFD9C61CC3
-20180606033204 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDB8F4F47
-20180606033802 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDBF98B5B
-20180606035103 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDCF1AF47
-20180606041154 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDE894FEF
-20180606041520 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFDEC4EE7B
-20180606043713 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE06AD163
-20180606053417 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE4C5AD13
-20180606060033 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE6C71C97
-20180606061040 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE77EB58B
-20180606062720 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFE8BC530F
-20180606065112 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEA7F6853
-20180606065226 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEA8EAA53
-20180606071446 2 6 100 5121 5 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEC3498CF
-20180606073822 2 6 100 5121 2 37585C4D659694D0B23500E18769F1EF93A776FF9FB92171358D9FE60A517E2CB91A4984A7E923B213CA5ED889D7CBD176B7B475315CB90EBD9920E41043A6C0BD37A8E2679AA7944ED273FDB1CBCAED3B2950BC73132CDE38789421CDDFAEC1C7662F3F9C3EA0C56758D7D3D0257499CE832FEF537F1BC17FFCB2360465A663AB629EF222B7C1E2ACF6368963B6A3D89E5617765B01D483C3BEB0F40D2BC4F4E0512CE41796C411A1EF20D70ED4F071EC56A24C52161D82B9222A52D56B0E48E118DDD1A5C01042E401B6724C80E939B3140A471CEA8C28E33883903283153A3EED07A506818930D61B420B0FF8D1B5F33A2E112B363D2B85A9FDE12AAA3DAE0E08945F4CE4E038A1B61624DD76CADFE172B0FE3C332F7B014634E7F4F80268EB6F1261F0667BF1FC4D9F0BA87C4CC42AC1261F7DA7C4508E3A70485F3D41B5B7AFA8DF0CA0CE61AF7A696B769FF69AB808AED3AE33F40E5E6DA7F8849349FB4A262965160C155B86AA0E13A8FB5EF1BD477790FD8949970B71DD508C971A88781DADEF4F67C1BF8E6BE1AC75B9E6CD74C471FB2D94B27269A9E30B671A52ABE673DAD632C1CC9C139468B852C06844D0D05A40D3A50D410DC4B8DD5B118626128CC5A2DA0093BE486F5D30E621DDB217B03AB97097733BD6E8D1CCFC7515D8761CF7EB0525483678785E29093865A60DA525D0A1D282501C27B1F6C7FEC64BED44F5409889BE78E049E22C5095E7EF4C9B7E88A49DF5CDBE6016A13072A28500AC00E64DB3CE3EBFC668CA0CB94CDDE8381F342E5CE4E2B1FC3067A295771DD0A8FFF308D5A47A91F1A67D8F77C3D20B88EAF17915867EE181DBC2DE8DF43B7179396A563292DB2966E79672BF8B7D0D0A3398A2E374C0E4A1C91DFEDF3BF93
20180606081635 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3819B8FC5F
20180606083850 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381B1D13EB
20180606084353 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381B65B5F7
@@ -235,38 +201,6 @@
20180607010449 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A385542D20F
20180607022006 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3859892A7B
20180607022905 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A385A0321EB
-20180607045001 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EA3B1267B
-20180607051849 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EA4D3FCDB
-20180607052645 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EA51AE857
-20180607074455 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EAABB372F
-20180607085512 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EAD8764F3
-20180607101435 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EB0B93D7F
-20180607122858 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EB613F7A7
-20180607163002 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EBF961A17
-20180607164733 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EC03FE5D7
-20180607170431 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EC0E41B93
-20180607210523 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ECA453803
-20180608000228 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED1125EF3
-20180608010403 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED3657E33
-20180608015201 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED537E7FB
-20180608023333 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED6C3867B
-20180608023523 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED6CC5597
-20180608025418 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0ED77890BB
-20180608052209 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EDD073603
-20180608064909 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EE0434A13
-20180608083049 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EE410EA0B
-20180608084134 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EE46EFA03
-20180608113212 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EEAB7B3A3
-20180608123538 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EED06D17F
-20180608133606 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EEF40EF2B
-20180608134723 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EEFA3A923
-20180608141153 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EF0866973
-20180608154036 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EF3C931BF
-20180608155132 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EF42B6B9B
-20180608192033 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EFBB82C37
-20180608203618 2 6 100 7167 5 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EFE7167C7
-20180608203803 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0EFE777583
-20180608231830 2 6 100 7167 2 E76114725DD41FA35A7DA1CF2A6C5701F689FC40E96BDAB540431472B92D5E38711F596734C76D1407BC11D5EECD10C52AE09D6EB46C7A119FE7BF2CE718363E5D9D06D972A80D1AEBE550FEF87C596C7B2FAB2FA6A27BE1D6CBFBD7A8B55FFBEFC78E6028AB4F83093162C4D8F9C4E72D45AEE3F788A1AA98A93B2E92DCC69739C3311002388723ED096B0FECB0698AB631108A2F5922453FA81DD178DDFB7A8E651E19E086F36684EF4958EF57E18393C173D07B594AEA0EAF5FE770F72550528C1637E341715CC80C74A2024CDEB2F949200E29BBFC0519F029CA2D45C4A66602553EF9A9086183018A055DFE19698B779908B119CB4C9E162680CA5E3EA471F4AF46F77DA5FF2A2C23C18509B1E8D0591B868A76163079461A83FBDAC95A5E8E4EB9152EAFCDFAD9CE5CDA7CE7846BEE134D52242152C4B671D1B2A05B927F6546A272DDEC50DDAE2D66B866C393F7CA3E2FF505FCC5187394BEEA2BC94F840B800884A8853A6A9AF1FB62837DDE066CC17EDDAD6921F0D96A7A9C2C1705CC024050201E93AF587FE1A480EDA8DCC257B0F7FF6A3006613250098090436BC3C63039846C8A2FD4180BB744D8584184C18F7B05BB110FC4D1C8C1D019EB072FC5C55DDBAE8272CAC153810A6D5A828B7B86350F656D350299264A111C8C876D7502D634C6014F324773E64FFE56DA602736355061CAF39DD29706111ED10F00BD80EE4FE076F6BA743F210C9DC502493A8974FEC1E2706C094A20C29EA7DB29B37D3BD709CD6942FB8ED5EE3D1C521AFFA3A242A13A5A705C458027118C950E656794F671373CE3A7A2D53C0C4BCDDF539D530ABE4A554ED76F7D0D43C1DFFEA320D1CD14A2BC5A5B2C04D84C17399C590D94D86F3E85EC66693D364379149FB7E5709C45B7077D8784114D14B640EB8F50DECCE1A83B041CD217155918BFE937BC0C4E8BBA30452A2F00A4D5F2091DD12C8849EA4989EAC9BCB7040C0049C3986D4F5BF0F3D55FD05A847D3FC4A58F4F5DB860333B1C60F8AE4646919D339B0E4342FEE167A214B25D17D25BDDB7F81BCC37551435C033A66BCD3775FCAE15CA9F311E90FBFF2A082AC2A6B8B0C7F4F5865BFB3B18DEE1E184587C3BA746869D70402BCE1AFAC1AA45BF4D8A6A390F076CA1D6381F7581E2A5718BF44EFB75E9864EBF5EB011FD7C0892C8500BFA01B422E4B67222C259A263863E66CC26C533D0796C0C17D4945D9E0ADDD961EAC0FC3E594B14C13B9A586B0F04486A93
20180607113212 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9285F38A617
20180607125146 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928617A82F3
20180607125328 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928617CB5DF
diff --git a/lib/public_key/src/pubkey_moduli.hrl b/lib/public_key/src/pubkey_moduli.hrl
index d3e2492cf2..768db624c7 100644
--- a/lib/public_key/src/pubkey_moduli.hrl
+++ b/lib/public_key/src/pubkey_moduli.hrl
@@ -352,75 +352,6 @@
822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908676438567},
{5,
822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908697685503}]},
- {5121,
- [{2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247097689699},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247187891059},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247233309283},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247329347539},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247374725179},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247374854083},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247416266563},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247449925747},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247491264043},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247565114563},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247602039643},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247648923259},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247676572003},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247749635347},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247795316107},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247845693523},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247846693459},
- {2,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247903649683},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247105253887},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247123422007},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247138876567},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247150015567},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247182428143},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247202352967},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247251099967},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247277733823},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247373770207},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247486491463},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247595077447},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247618301767},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247645016047},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247783283863},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247816131343},
- {5,
- 649437634112526011781048553400039087345326903154523759350403591156064026924461442249265424643851483793427933209842971350578174113891441825577284685965852170818096276564472575980385637569538579237402539408651576344680653270161629667112355235907244563250700929011643383515531122864487687325699022847401349887930148743573324935926928038313274118780408648738039221552094286634605859059178302001609063051473627616638916986695467354111409872240377448596882457893385604785675125747799925704521626444410537947809612042456889585358493384339367397319430466068497259487250009990226983476303290182605464299191144834590976900215207184217290547939862278004600042733098488459539365766704233072540349790910413963048455919274571091600102388120830520138960918238026360535071025369430480571742657175404099199715243175884516644982333939980185912023546244471169175154232817129035386017126612372249727029415960226233559719423091324216204450258205068541788852628274234145551296430267231614519548422573530219115334315814963859220772016127905259664901596292960624357867171314754794327851281187544474064975723856559261998464776997766060743177575177887669315503357551968629467385805021951612024977234727345596392623743650652821546588655008745166946053122284578514217986359571614564066926642313354080995691975795001216172305325876725224168312406194959039369235312034402577256851071978396414051789255283218481832719899346830805746190414783360826783268783647194536819312776246291560322670087150506500394384601386261997874464354519244142316219347283660495896740247874345167}]},
{6143,
[{2,
30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066212697067},
@@ -480,71 +411,6 @@
30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067042481887},
{5,
30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067188249103}]},
- {7167,
- [{2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680505796219},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680524856539},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680670831859},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680995675027},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681153034243},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681267142387},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681306144307},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681336711163},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681362638459},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681374503099},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681467737603},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681522006547},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681585814027},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681591978499},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681697407907},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681773510443},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681779980579},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681794840947},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681855986587},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284682028742019},
- {2,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284682126322323},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680529504343},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680623896367},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680724430207},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680814262183},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680973785623},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284680984913367},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681363215767},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681736147327},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681849549247},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284681982651447},
- {5,
- 5483947689873238016293916031421210417715226198450458695278359214939920808903888754748291585234470514731095293158971577871290333956546390471923967166891926796058037943347061391932048683243406115629059207198430761405517792845307599528545123275907240829958638010654676409407473464540147054022768326380533144139109013796005070619515692497303229683409723476100264437337159592967071649572068146217379004726298805073131642749312292639037974687912276595434011484665633472741970437405242931540792817150021104152269103538845906716294609703037973874968257574699425342614963850129729638055165011318321314629257017448744791130817504976352049315558175084707575517905220240735436472311376085977023193255767115772199401681050675227245864337841813577099951328506716260252484525951496988402157538736606893316558602219804539468211692272341101231081798647407433475330661334010047363328925076029072733284928506274503591566463356567449951050328939372527077820435552083641057965091365289077453354175453158803766717082697605135002698550392387018215808881309906132288850897899530025875371847565845964186403727130406970585738244224109459935326058926178367135154001854890789551481230848123840375019517586126229348925204229138925157417388983071508190365878773959469248844627811548238703202907823260627705881418371964608641916875906309702255332357870246656733850484860625288965209661089574538795660416296959228913342040037715375469749366782116594607018721130210724633134051682028201789300859780675503521182677498151404274736590115271652257881815395804591347270645487515405426176207583246761514846190105223591830994843572131787042752062568982393789415091692293114059135480055118138148767250658263869768994686391725791746769853583344796533031355717997717521032986544321281377626382079046164167636841143008587025918057095843339228816609264878115677918487854067887356202214595419884175437682477994901012403352228510424776160081628734502208471530373704829323453838286290450475142257346198410524038065099740082374843587568140564545670658917308004231061168599338344693117101685656038296427353228994834347618154742061252460559481017139006630352773110812670787299045754161442872626284682028345287}]},
{8191,
[{2,
881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408345391859},
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index f7faadb8fb..5e9e463323 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.6
+PUBLIC_KEY_VSN = 1.6.1
diff --git a/lib/reltool/doc/src/Makefile b/lib/reltool/doc/src/Makefile
index e378cdf980..8daafb7a2b 100644
--- a/lib/reltool/doc/src/Makefile
+++ b/lib/reltool/doc/src/Makefile
@@ -88,6 +88,7 @@ clean clean_docs:
fi \
done
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 5bfbee966b..0da9279c80 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -806,7 +806,7 @@ target_spec() = [target_spec()]
<name>stop(Pid) -> ok | {error, Reason}</name>
<fsummary>Stop a server or window process</fsummary>
<type>
- <v>Pid = server_pid() | window_pid()()</v>
+ <v>Pid = server_pid() | window_pid()</v>
<v>Reason = reason()</v>
</type>
<desc><p>Stop a server or window process</p></desc>
diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl
index af71b0cf2a..47aba77835 100644
--- a/lib/reltool/src/reltool_server.erl
+++ b/lib/reltool/src/reltool_server.erl
@@ -526,7 +526,7 @@ analyse(#state{sys=Sys} = S, Apps, Status) ->
%% is included in a release (rel spec - see apps_in_rels above).
%% Then initiate the same for each module, and check that there
%% are no duplicated module names (in different applications)
- %% where we can not decide which one to use.
+ %% where we cannot decide which one to use.
%% Write all #app to app_tab and all #mod to mod_tab.
Status2 = apps_init_is_included(S, Apps, RelApps, Status),
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index 4e1937d479..fc976bfb94 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -1038,7 +1038,7 @@ create_standalone_app(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate standalone system with inlined archived application
-%% Check that the inlined app can not be explicitly configured
+%% Check that the inlined app cannot be explicitly configured
create_standalone_app_clash(Config) ->
%% Create archive
@@ -1658,7 +1658,7 @@ set_apps_inlined(Config) ->
?m(true, Someapp1#app.is_included),
?m(true, Someapp1#app.is_pre_included),
- %% Check that inlined app can not be configured
+ %% Check that inlined app cannot be configured
Someapp2 = Someapp1#app{incl_cond=exclude},
?msym({error,
"Application someapp is inlined in '*escript* someapp'. "
diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile
index b788ef55ff..2399ed51e0 100644
--- a/lib/runtime_tools/doc/src/Makefile
+++ b/lib/runtime_tools/doc/src/Makefile
@@ -120,6 +120,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 3262cafefc..ae60b610ed 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -113,7 +113,7 @@
<p>The imported variables will be replaced by match_spec
<c>const</c> expressions, which is consistent with the
static scoping for Erlang <c>fun()</c>s. Local or global
- function calls can not be in the guard or body of the fun
+ function calls cannot be in the guard or body of the fun
however. Calls to builtin match_spec functions of course is
allowed:</p>
<pre>
@@ -756,7 +756,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
<c>cant_add_local_node</c> is returned.
</p>
<p>If a trace port (see <seealso marker="#trace_port-2"><c>trace_port/2</c></seealso>) is
- running on the local node, remote nodes can not be traced with
+ running on the local node, remote nodes cannot be traced with
a tracer process. The error reason
<c>cant_trace_remote_pid_to_local_port</c> is returned. A
trace port can however be started on the remote node with the
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index 063b19e533..3a24986381 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -94,7 +94,7 @@ sys_info() ->
{port_limit, erlang:system_info(port_limit)},
{port_count, erlang:system_info(port_count)},
{ets_limit, erlang:system_info(ets_limit)},
- {ets_count, length(ets:all())},
+ {ets_count, erlang:system_info(ets_count)},
{dist_buf_busy_limit, erlang:system_info(dist_buf_busy_limit)}
| MemInfo].
diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl
index 136ee55b54..8f7bfa195b 100644
--- a/lib/runtime_tools/src/system_information.erl
+++ b/lib/runtime_tools/src/system_information.erl
@@ -400,7 +400,6 @@ os_getenv_erts_specific() ->
"ERL_MALLOC_LIB",
"ERL_MAX_PORTS",
"ERL_MAX_ETS_TABLES",
- "ERL_NO_VFORK",
"ERL_NO_KERNEL_POLL",
"ERL_THREAD_POOL_SIZE",
"ERLC_EMULATOR",
diff --git a/lib/sasl/doc/src/Makefile b/lib/sasl/doc/src/Makefile
index baf563ca62..8e1e8b502c 100644
--- a/lib/sasl/doc/src/Makefile
+++ b/lib/sasl/doc/src/Makefile
@@ -101,6 +101,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 28829132a1..bef4268d3a 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -890,7 +890,7 @@ read_rep(Fd, FilePosition, Device, Abort, Log) ->
handle_bad_form(Date, Msg, Device, Abort, Log) ->
io:format("rb: ERROR! A report on bad form was encountered. " ++
- "It can not be printed to the log.~n~n"),
+ "It cannot be printed to the log.~n~n"),
io:format("Details:~n~p ~tp~n~n", [Date,Msg]),
case {Abort,Device,open_log_file(Log)} of
{true,standard_io,standard_io} ->
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index 7570b74c1a..48feac1a21 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1120,7 +1120,7 @@ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
{ok,[FC]} ->
FC;
{error,Error1} ->
- io:format("Warning: ~w can not read ~tp: ~tp~n",
+ io:format("Warning: ~w cannot read ~tp: ~tp~n",
[?MODULE,FromFile,Error1]),
[]
end,
@@ -1130,7 +1130,7 @@ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
{ok,[ToConfig]} ->
[lists:keyfind(App,1,ToConfig) || App <- [kernel,stdlib,sasl]];
{error,Error2} ->
- io:format("Warning: ~w can not read ~tp: ~tp~n",
+ io:format("Warning: ~w cannot read ~tp: ~tp~n",
[?MODULE,ToFile,Error2]),
[false,false,false]
end,
diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl
index ca97515299..bf18691687 100644
--- a/lib/sasl/src/release_handler_1.erl
+++ b/lib/sasl/src/release_handler_1.erl
@@ -147,7 +147,7 @@ split_instructions([], Before) ->
%% If PrePurgeMethod == soft_purge, the function will succeed
%% only if there is no process running old code of any of the
%% modules. Else it will throw {error,Mod}, where Mod is the
-%% first module found that can not be soft_purged.
+%% first module found that cannot be soft_purged.
%%
%% If PrePurgeMethod == brutal_purge, the function will
%% always succeed and return a list of all modules that are
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl
index e38d0cfa7b..5429008a5f 100644
--- a/lib/sasl/test/installer.erl
+++ b/lib/sasl/test/installer.erl
@@ -905,7 +905,7 @@ start_client(TestNode,Client,Sname) ->
wait_started(TestNode,Node)
after 30000 ->
?print([{start_client,failed,Node},net_adm:ping(Node)]),
- ?fail({"can not start", Node})
+ ?fail({"cannot start", Node})
end.
start_client_unix(TestNode,Sname,Node) ->
diff --git a/lib/sasl/test/rb_SUITE.erl b/lib/sasl/test/rb_SUITE.erl
index 2b6e452d14..e5ca1775d5 100644
--- a/lib/sasl/test/rb_SUITE.erl
+++ b/lib/sasl/test/rb_SUITE.erl
@@ -423,7 +423,7 @@ start_stop_log(Config) ->
StdioResult2 = capture(fun() -> rb:log_list() end),
{ok,<<>>} = file:read_file(OutFile),
- %% Test that standard_io is used if log file can not be opened
+ %% Test that standard_io is used if log file cannot be opened
ok = rb:start_log(filename:join(nonexistingdir,"newfile.txt")),
StdioResult = capture(fun() -> rb:show(1) end),
{ok,<<>>} = file:read_file(OutFile),
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index 863b765645..a03932133e 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -21,6 +21,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([gen_server_crash/1, gen_server_crash_unicode/1]).
+-export([legacy_gen_server_crash/1, legacy_gen_server_crash_unicode/1]).
-export([crash_me/0,start_link/0,init/1,handle_cast/2,terminate/2]).
@@ -29,7 +30,10 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [gen_server_crash, gen_server_crash_unicode].
+ [gen_server_crash,
+ gen_server_crash_unicode,
+ legacy_gen_server_crash,
+ legacy_gen_server_crash_unicode].
groups() ->
[].
@@ -52,17 +56,77 @@ gen_server_crash(Config) ->
gen_server_crash_unicode(Config) ->
gen_server_crash(Config, unicode).
+legacy_gen_server_crash(Config) ->
+ legacy_gen_server_crash(Config,latin1).
+
+legacy_gen_server_crash_unicode(Config) ->
+ legacy_gen_server_crash(Config,unicode).
+
gen_server_crash(Config, Encoding) ->
+ TC = list_to_atom(lists:concat([?FUNCTION_NAME,"_",Encoding])),
+ PrivDir = filename:join(?config(priv_dir,Config),?MODULE),
+ ConfigFileName = filename:join(PrivDir,TC),
+ KernelLog = filename:join(PrivDir,lists:concat([TC,"_kernel.log"])),
+ SaslLog = filename:join(PrivDir,lists:concat([TC,"_sasl.log"])),
+ KernelConfig = [{logger,[{handler,default,logger_std_h,
+ #{config=>#{type=>{file,KernelLog}}}}]},
+ {logger_sasl_compatible,true}],
+ Modes = [write, {encoding, Encoding}],
+ SaslConfig = [{sasl_error_logger,{file,SaslLog,Modes}}],
+ ok = filelib:ensure_dir(SaslLog),
+
+ ok = file:write_file(ConfigFileName ++ ".config",
+ io_lib:format("[{kernel, ~p},~n{sasl, ~p}].",
+ [KernelConfig,SaslConfig])),
+ {ok,Node} =
+ test_server:start_node(
+ TC, peer,
+ [{args, ["-pa ",filename:dirname(code:which(?MODULE)),
+ " -boot start_sasl -kernel start_timer true "
+ "-config ",ConfigFileName]}]),
+
+ %% Set depth
+ ok = rpc:call(Node,logger,update_formatter_config,[default,depth,30]),
+ ok = rpc:call(Node,logger,update_formatter_config,[sasl,depth,30]),
+
+ %% Make sure remote node logs it's own logs, and current node does
+ %% not log them.
+ ok = rpc:call(Node,logger,remove_handler_filter,[default,remote_gl]),
+ ok = rpc:call(Node,logger,remove_handler_filter,[sasl,remote_gl]),
+ ok = logger:add_primary_filter(no_remote,{fun(#{meta:=#{pid:=Pid}},_)
+ when node(Pid)=/=node() -> stop;
+ (_,_) -> ignore
+ end,[]}),
+ ct:log("Local node Logger config:~n~p",
+ [rpc:call(Node,logger,get_config,[])]),
+ ct:log("Remote node Logger config:~n~p",
+ [rpc:call(Node,logger,get_config,[])]),
+ ct:log("Remote node error_logger handlers: ~p",
+ [rpc:call(Node,error_logger,which_report_handlers,[])]),
+
+ ok = rpc:call(Node,?MODULE,crash_me,[]),
+
+ test_server:stop_node(Node),
+ ok = logger:remove_primary_filter(no_remote),
+
+ check_file(KernelLog, utf8, 70000, 150000),
+ check_file(SaslLog, Encoding, 70000, 150000),
+
+ ok = file:delete(KernelLog),
+ ok = file:delete(SaslLog),
+
+ ok.
+
+legacy_gen_server_crash(Config, Encoding) ->
StopFilter = {fun(_,_) -> stop end, ok},
logger:add_handler_filter(default,stop_all,StopFilter),
+ logger:add_handler_filter(sasl,stop_all,StopFilter),
logger:add_handler_filter(cth_log_redirect,stop_all,StopFilter),
try
do_gen_server_crash(Config, Encoding)
after
- ok = application:unset_env(kernel, logger_sasl_compatible),
- ok = application:unset_env(sasl, sasl_error_logger),
- ok = application:unset_env(kernel, error_logger_format_depth),
logger:remove_handler_filter(default,stop_all),
+ logger:remove_handler_filter(sasl,stop_all),
logger:remove_handler_filter(cth_log_redirect,stop_all)
end,
ok.
@@ -74,22 +138,17 @@ do_gen_server_crash(Config, Encoding) ->
SaslLog = filename:join(LogDir, "sasl.log"),
ok = filelib:ensure_dir(SaslLog),
- application:stop(sasl),
Modes = [write, {encoding, Encoding}],
- ok = application:set_env(kernel, logger_sasl_compatible, true),
- ok = application:set_env(sasl, sasl_error_logger, {file,SaslLog,Modes},
- [{persistent,true}]),
application:set_env(kernel, error_logger_format_depth, 30),
error_logger:logfile({open,KernelLog}),
- application:start(sasl),
+ error_logger:add_report_handler(sasl_report_file_h,{SaslLog,Modes,all}),
ct:log("Logger config:~n~p",[logger:get_config()]),
ct:log("error_logger handlers: ~p",[error_logger:which_report_handlers()]),
crash_me(),
-
error_logger:logfile(close),
- application:stop(sasl),
+ error_logger:delete_report_handler(sasl_report_file_h),
check_file(KernelLog, utf8, 70000, 150000),
check_file(SaslLog, Encoding, 70000, 150000),
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 1827974866..6c913850b9 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -1654,7 +1654,7 @@ abnormal_relup(Config) when is_list(Config) ->
ok.
-%% make_relup: Check relup can not be created is sasl is not in rel file.
+%% make_relup: Check relup cannot be created is sasl is not in rel file.
no_sasl_relup(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
{Dir1,Name1} = create_script(latest1_no_sasl,Config),
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index 3ebee792f9..a6a9477b05 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -140,6 +140,7 @@ clean_man:
clean_html:
@echo "cleaning html:"
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
$(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
@echo "processing $*"
diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl
index 57507a36e8..97b8ddf7c4 100644
--- a/lib/snmp/src/agent/snmpa_set_lib.erl
+++ b/lib/snmp/src/agent/snmpa_set_lib.erl
@@ -46,9 +46,9 @@
%%* 6) IF value is outside the acceptable range THEN wrongValue.
%% 7) IF variable does not exist and could not ever be created
%% THEN noCreation.
-%% 8) IF variable can not be created now THEN inconsistentName.
-%% 9) IF value can not be set now THEN inconsistentValue.
-%%* 9) IF instances of the variable can not be modified THEN notWritable.
+%% 8) IF variable cannot be created now THEN inconsistentName.
+%% 9) IF value cannot be set now THEN inconsistentValue.
+%%* 9) IF instances of the variable cannot be modified THEN notWritable.
%% 10) IF an unavailable resource is needed THEN resourceUnavailable.
%% 11) IF any other error THEN genErr.
%% 12) Otherwise ok!
diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl
index e75016f7ec..293d1f3ccf 100644
--- a/lib/snmp/src/agent/snmpa_trap.erl
+++ b/lib/snmp/src/agent/snmpa_trap.erl
@@ -830,11 +830,11 @@ do_send_v1_trap(Enter, Spec, V1Res, NVbs, ExtraInfo, NetIf, SysUpTime) ->
case lists:keyfind(transportDomainUdpIpv4, 1, Transports) of
false ->
?vtrace(
- "snmpa_trap: can not send v1 trap "
+ "snmpa_trap: cannot send v1 trap "
"without IPv4 domain: ~p",
[Transports]),
user_err(
- "snmpa_trap: can not send v1 trap "
+ "snmpa_trap: cannot send v1 trap "
"without IPv4 domain: ~p",
[Transports]);
DomainAddr ->
diff --git a/lib/snmp/test/test-mibs/ALARM-MIB.mib b/lib/snmp/test/test-mibs/ALARM-MIB.mib
index 18e43d4b4b..10d2adbff9 100644
--- a/lib/snmp/test/test-mibs/ALARM-MIB.mib
+++ b/lib/snmp/test/test-mibs/ALARM-MIB.mib
@@ -330,7 +330,7 @@ alarmModelRowStatus OBJECT-TYPE
cannot be used as an alarm suppression mechanism. Entries
that are notInService will disappear as described in RFC2579.
- This row can not be modified while it is being
+ This row cannot be modified while it is being
referenced by a value of alarmActiveModelPointer. In these
cases, an error of `inconsistentValue' will be returned to
the manager.
diff --git a/lib/snmp/test/test-mibs/SNMPv2-TC.mib b/lib/snmp/test/test-mibs/SNMPv2-TC.mib
index fd6a728ab5..1d75c4bbd8 100644
--- a/lib/snmp/test/test-mibs/SNMPv2-TC.mib
+++ b/lib/snmp/test/test-mibs/SNMPv2-TC.mib
@@ -454,7 +454,7 @@ value | | see 1| ->C| ->D
associated with this column or that there is no
conceptual row for which this column would be
accessible in the MIB view used by the retrieval. As
- such, the management station can not issue any
+ such, the management station cannot issue any
management protocol set operations to create an
instance of this column.
@@ -576,7 +576,7 @@ value | | see 1| ->C| ->D
associated with this column or that there is no
conceptual row for which this column would be
accessible in the MIB view used by the retrieval. As
- such, the management station can not issue any
+ such, the management station cannot issue any
management protocol set operations to create an
instance of this column.
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index 425322f6ca..77fa356092 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -119,6 +119,7 @@ html: images $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECS_FILES)
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index c9aa877a7f..58e8c9ab5b 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -31,7 +31,6 @@
</header>
<section><title>Ssh 4.7</title>
-
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -190,6 +189,33 @@
</item>
</list>
</section>
+</section>
+
+<section><title>Ssh 4.6.9.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SFTP clients reported the error reason <c>""</c> if a
+ non-OTP sftp server was killed during a long file
+ transmission.</p>
+ <p>
+ Now the signal name (for example <c>"KILL"</c>) will be
+ the error reason if the server's reason is empty.</p>
+ <p>
+ The documentation also lacked type information about this
+ class of errors.</p>
+ <p>
+ Own Id: OTP-15148 Aux Id: ERIERL-194 </p>
+ </item>
+ <item>
+ <p>
+ Fix ssh_sftp decode error for sftp protocol version 4</p>
+ <p>
+ Own Id: OTP-15149 Aux Id: ERIERL-199 </p>
+ </item>
+ </list>
+ </section>
</section>
@@ -2739,7 +2765,7 @@
</item>
<item>
<p>
- Fixed internal error on when client and server can not
+ Fixed internal error on when client and server cannot
agree o which authmethod to use.</p>
<p>
Own Id: OTP-10731 Aux Id: seq12237 </p>
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index f238bf2ca8..3bc62073a2 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -46,7 +46,7 @@
In that encrypted connection one or more channels could be opened with
<seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
</p>
- <p>Each channel is an isolated "pipe" between a client-side process and a server-side process. Thoose process
+ <p>Each channel is an isolated "pipe" between a client-side process and a server-side process. Those process
pairs could handle for example file transfers (sftp) or remote command execution (shell, exec and/or cli).
If a custom shell is implemented, the user of the client could execute the special commands remotely. Note that
the user is not necessarily a human but probably a system interfacing the SSH app.
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index 4d2337c30a..ea55126cb3 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -46,9 +46,9 @@
<taglist>
<tag><c>reason()</c></tag>
<item>
- <p>= <c>atom()</c> A description of the reason why an operation failed.</p>
+ <p>= <c>atom() | string() | tuple() </c>A description of the reason why an operation failed.</p>
<p>
- The value is formed from the sftp error codes in the protocol-level responses as defined in
+ The <c>atom()</c> value is formed from the sftp error codes in the protocol-level responses as defined in
<url href="https://tools.ietf.org/id/draft-ietf-secsh-filexfer-13.txt">draft-ietf-secsh-filexfer-13.txt</url>
section 9.1.
</p>
@@ -57,6 +57,10 @@
E.g. the error code <c>SSH_FX_NO_SUCH_FILE</c>
will cause the <c>reason()</c> to be <c>no_such_file</c>.
</p>
+ <p>The <c>string()</c> reason is the error information from the server in case of an exit-signal. If that information is empty, the reason is the exit signal name.
+ </p>
+ <p>The <c>tuple()</c> reason are other errors like the <c>{exit_status,integer()}</c> if the exit status is not 0.
+ </p>
</item>
<tag><c>connection_ref() =</c></tag>
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 9631427749..01c44cb371 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -492,4 +492,29 @@
-define(wr_record(N), ?wr_record(N, [])).
+%% Circular trace buffer macros
+
+-record(circ_buf_entry,
+ {
+ module,
+ line,
+ function,
+ pid = self(),
+ value
+ }).
+
+-define(CIRC_BUF_IN(VALUE),
+ ssh_dbg:cbuf_in(
+ #circ_buf_entry{module = ?MODULE,
+ line = ?LINE,
+ function = {?FUNCTION_NAME,?FUNCTION_ARITY},
+ pid = self(),
+ value = (VALUE)
+ })
+ ).
+
+-define(CIRC_BUF_IN_ONCE(VALUE),
+ ((fun(V) -> ?CIRC_BUF_IN(V), V end)(VALUE))
+ ).
+
-endif. % SSH_HRL defined
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index b53c09b17d..4fe15b24d3 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -54,7 +54,13 @@
start_tracer/0, start_tracer/1,
on/1, on/0,
off/1, off/0,
- go_on/0
+ go_on/0,
+ %% Circular buffer
+ cbuf_start/0, cbuf_start/1,
+ cbuf_stop_clear/0,
+ cbuf_in/1,
+ cbuf_list/0,
+ fmt_cbuf_items/0, fmt_cbuf_item/1
]).
-export([shrink_bin/1,
@@ -71,6 +77,8 @@
-behaviour(gen_server).
-define(SERVER, ?MODULE).
+-define(CALL_TIMEOUT, 15000). % 3x the default
+
%%%================================================================
-define(ALL_DBG_TYPES, get_all_dbg_types()).
@@ -107,7 +115,7 @@ start_tracer(WriteFun) when is_function(WriteFun,3) ->
start_tracer(WriteFun, InitAcc) when is_function(WriteFun, 3) ->
Handler =
fun(Arg, Acc0) ->
- try_all_types_in_all_modules(gen_server:call(?SERVER, get_on),
+ try_all_types_in_all_modules(gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT),
Arg, WriteFun,
Acc0)
end,
@@ -122,7 +130,7 @@ off() -> off(?ALL_DBG_TYPES). % A bit overkill...
off(Type) -> switch(off, Type).
go_on() ->
- IsOn = gen_server:call(?SERVER, get_on),
+ IsOn = gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT),
on(IsOn).
%%%----------------------------------------------------------------
@@ -253,7 +261,7 @@ switch(X, Types) when is_list(Types) ->
end,
case lists:usort(Types) -- ?ALL_DBG_TYPES of
[] ->
- gen_server:call(?SERVER, {switch,X,Types});
+ gen_server:call(?SERVER, {switch,X,Types}, ?CALL_TIMEOUT);
L ->
{error, {unknown, L}}
end.
@@ -331,3 +339,103 @@ ts({_,_,Usec}=Now) when is_integer(Usec) ->
io_lib:format("~.2.0w:~.2.0w:~.2.0w.~.6.0w",[HH,MM,SS,Usec]);
ts(_) ->
"-".
+
+%%%================================================================
+-define(CIRC_BUF, circ_buf).
+
+cbuf_start() ->
+ cbuf_start(20).
+
+cbuf_start(CbufMaxLen) ->
+ put(?CIRC_BUF, {CbufMaxLen,queue:new()}),
+ ok.
+
+
+cbuf_stop_clear() ->
+ case erase(?CIRC_BUF) of
+ undefined ->
+ [];
+ {_CbufMaxLen,Queue} ->
+ queue:to_list(Queue)
+ end.
+
+
+cbuf_in(Value) ->
+ case get(?CIRC_BUF) of
+ undefined ->
+ disabled;
+ {CbufMaxLen,Queue} ->
+ UpdatedQueue =
+ try queue:head(Queue) of
+ {Value, TS0, Cnt0} ->
+ %% Same Value as last saved in the queue
+ queue:in_r({Value, TS0, Cnt0+1},
+ queue:drop(Queue)
+ );
+ _ ->
+ queue:in_r({Value, erlang:timestamp(), 1},
+ truncate_cbuf(Queue, CbufMaxLen)
+ )
+ catch
+ error:empty ->
+ queue:in_r({Value, erlang:timestamp(), 1}, Queue)
+ end,
+ put(?CIRC_BUF, {CbufMaxLen,UpdatedQueue}),
+ ok
+ end.
+
+
+cbuf_list() ->
+ case get(?CIRC_BUF) of
+ undefined ->
+ [];
+ {_CbufMaxLen,Queue} ->
+ queue:to_list(Queue)
+ end.
+
+
+truncate_cbuf(Q, CbufMaxLen) ->
+ case queue:len(Q) of
+ N when N>=CbufMaxLen ->
+ truncate_cbuf(element(2,queue:out_r(Q)), CbufMaxLen);
+ _ ->
+ Q
+ end.
+
+fmt_cbuf_items() ->
+ lists:flatten(
+ io_lib:format("Circular trace buffer. Latest item first.~n~s~n",
+ [case get(?CIRC_BUF) of
+ {Max,_} ->
+ L = cbuf_list(),
+ [io_lib:format("==== ~.*w: ~s~n",[num_digits(Max),N,fmt_cbuf_item(X)]) ||
+ {N,X} <- lists:zip(lists:seq(1,length(L)), L)
+ ];
+ _ ->
+ io_lib:format("Not started.~n",[])
+ end])).
+
+
+num_digits(0) -> 1;
+num_digits(N) when N>0 -> 1+trunc(math:log10(N)).
+
+
+fmt_cbuf_item({Value, TimeStamp, N}) ->
+ io_lib:format("~s~s~n~s~n",
+ [fmt_ts(TimeStamp),
+ [io_lib:format(" (Repeated ~p times)",[N]) || N>1],
+ fmt_value(Value)]).
+
+
+fmt_ts(TS = {_,_,Us}) ->
+ {{YY,MM,DD},{H,M,S}} = calendar:now_to_universal_time(TS),
+ io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~.6.0w UTC",[YY,MM,DD,H,M,S,Us]).
+
+fmt_value(#circ_buf_entry{module = M,
+ line = L,
+ function = {F,A},
+ pid = Pid,
+ value = V}) ->
+ io_lib:format("~p:~p ~p/~p ~p~n~s",[M,L,F,A,Pid,fmt_value(V)]);
+fmt_value(Value) ->
+ io_lib:format("~p",[Value]).
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index 6e720a47b7..1b2ba5a50b 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -798,13 +798,22 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}},
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, Signal, Error0, _}},
State0) ->
+ Error =
+ case Error0 of
+ "" -> Signal;
+ _ -> Error0
+ end,
State = reply_all(State0, {error, Error}),
{stop, ChannelId, State};
handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State0) ->
- State = reply_all(State0, {error, {exit_status, Status}}),
+ State =
+ case State0 of
+ 0 -> State0;
+ _ -> reply_all(State0, {error, {exit_status, Status}})
+ end,
{stop, ChannelId, State}.
%%--------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 7ee762dcee..278f6a9780 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -125,9 +125,9 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
- Report = io_lib:format("Connection closed by peer ~n Error ~p~n",
- [Error]),
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, Signal, Error, _}}, State) ->
+ Report = io_lib:format("Connection closed by peer signal ~p~n Error ~p~n",
+ [Signal,Error]),
error_logger:error_report(Report),
{stop, ChannelId, State};
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 9ec16b420d..b6d7aa0b1b 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -128,9 +128,9 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()].
supported_algorithms(kex) ->
select_crypto_supported(
[
- {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]},
- {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]},
- {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]},
+ {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {curves,secp384r1}, {hashs,sha384}]},
+ {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {curves,secp521r1}, {hashs,sha512}]},
+ {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {curves,secp256r1}, {hashs,sha256}]},
%% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves
%% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
{'curve25519-sha256', [{public_keys,eddh}, {curves,x25519}, {hashs,sha256}]},
@@ -147,9 +147,9 @@ supported_algorithms(kex) ->
supported_algorithms(public_key) ->
select_crypto_supported(
[
- {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]},
- {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]},
- {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]},
+ {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {curves,secp384r1}]},
+ {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {curves,secp521r1}]},
+ {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {curves,secp256r1}]},
{'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]},
{'rsa-sha2-256', [{public_keys,rsa}, {hashs,sha256} ]},
{'rsa-sha2-512', [{public_keys,rsa}, {hashs,sha512} ]},
@@ -174,9 +174,9 @@ supported_algorithms(cipher) ->
supported_algorithms(mac) ->
same(
select_crypto_supported(
- [{'hmac-sha2-256', [{hashs,sha256}]},
- {'hmac-sha2-512', [{hashs,sha512}]},
- {'hmac-sha1', [{hashs,sha}]},
+ [{'hmac-sha2-256', [{macs,hmac}, {hashs,sha256}]},
+ {'hmac-sha2-512', [{macs,hmac}, {hashs,sha512}]},
+ {'hmac-sha1', [{macs,hmac}, {hashs,sha}]},
{'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
{'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]}
]
@@ -1978,15 +1978,10 @@ supported_algorithms(Key, BlackList) ->
select_crypto_supported(L) ->
- Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()],
+ Sup = crypto:supports(),
[Name || {Name,CryptoRequires} <- L,
crypto_supported(CryptoRequires, Sup)].
-crypto_supported_curves() ->
- try crypto:ec_curves()
- catch _:_ -> []
- end.
-
crypto_supported(Conditions, Supported) ->
lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) ->
crypto_name_supported(Tag,CryptoName,Supported);
@@ -1996,7 +1991,11 @@ crypto_supported(Conditions, Supported) ->
end, Conditions).
crypto_name_supported(Tag, CryptoName, Supported) ->
- lists:member(CryptoName, proplists:get_value(Tag,Supported,[])).
+ Vs = case proplists:get_value(Tag,Supported,[]) of
+ [] when Tag == curves -> crypto:ec_curves();
+ L -> L
+ end,
+ lists:member(CryptoName, Vs).
len_supported(Name, Len) ->
try
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index e1680c120e..7bb9c2d101 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -734,7 +734,7 @@ decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
{Type,Tail2} =
if Vsn =< 3 ->
{?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
- Vsn >= 5 ->
+ true ->
<<?BYTE(T), TL/binary>> = Tail,
{T, TL}
end,
diff --git a/lib/ssh/test/ssh_dbg_SUITE.erl b/lib/ssh/test/ssh_dbg_SUITE.erl
index 5439817d10..ab7918fa90 100644
--- a/lib/ssh/test/ssh_dbg_SUITE.erl
+++ b/lib/ssh/test/ssh_dbg_SUITE.erl
@@ -38,11 +38,20 @@ suite() ->
{timetrap,{seconds,60}}].
all() ->
- [basic,
- dbg_alg_terminate,
- dbg_ssh_messages,
- dbg_connections,
- dbg_channels
+ [{group, dbg},
+ {group, circ_buf}
+ ].
+
+groups() ->
+ [{dbg, [], [dbg_basic,
+ dbg_alg_terminate,
+ dbg_ssh_messages,
+ dbg_connections,
+ dbg_channels]},
+ {circ_buf, [], [cb_basic,
+ cb_print,
+ cb_macros_print
+ ]}
].
%%--------------------------------------------------------------------
@@ -82,7 +91,7 @@ end_per_testcase(_TC, Config) ->
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-basic(_Config) ->
+dbg_basic(_Config) ->
L0 = ssh_dbg:start(),
true = is_pid(whereis(ssh_dbg)),
true = is_list(L0),
@@ -342,6 +351,53 @@ dbg_channels(Config) ->
stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid).
%%--------------------------------------------------------------------
+cb_basic(_Config) ->
+ %% Check that the circular buffer is disabled at start:
+ [] = ssh_dbg:cbuf_list(),
+ disabled = ssh_dbg:cbuf_in(anything),
+ [] = ssh_dbg:cbuf_list(),
+ %% Start it and enter three values, first is duplicated;
+ ok = ssh_dbg:cbuf_start(3),
+ ok = ssh_dbg:cbuf_in(v1),
+ ok = ssh_dbg:cbuf_in(v1),
+ ok = ssh_dbg:cbuf_in(v2),
+ ok = ssh_dbg:cbuf_in(v3),
+ [{v3,_,1}, {v2,_,1}, {v1,_,2}] = ssh_dbg:cbuf_list(),
+ %% Check that a fourth value erase the first entered:
+ ok = ssh_dbg:cbuf_in(v4),
+ [{v4,_,1}, {v3,_,1}, {v2,_,1}] = ssh_dbg:cbuf_list(),
+ %% Check that entering a value that is in the tail but not in the head is treated as a new value:
+ ok = ssh_dbg:cbuf_in(v2),
+ [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_list(),
+ %% Stop and check that the buffer is returned:
+ [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_stop_clear(),
+ %% Stopping a stopped buffer returns empty:
+ [] = ssh_dbg:cbuf_stop_clear(),
+ %% Check that a value can't be entered in a stopped buffer:
+ disabled = ssh_dbg:cbuf_in(v2).
+
+%%--------------------------------------------------------------------
+cb_print(_Config) ->
+ ssh_dbg:cbuf_start(),
+ [begin
+ ssh_dbg:cbuf_in(V),
+ ct:log("Enter ~p",[V])
+ end || V <- lists:seq(1,10)],
+ ct:log("~s",[ssh_dbg:fmt_cbuf_items()]),
+ ssh_dbg:cbuf_stop_clear().
+
+%%--------------------------------------------------------------------
+cb_macros_print(_Config) ->
+ ssh_dbg:cbuf_start(),
+ [begin
+ V = {test,V0},
+ ?CIRC_BUF_IN(V),
+ ct:log("Enter ~p",[V])
+ end || V0 <- lists:seq(1,5)],
+ ct:log("~s",[ssh_dbg:fmt_cbuf_items()]),
+ ssh_dbg:cbuf_stop_clear().
+
+%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 6060e50d31..c3572b5b70 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
SSH_VSN = 4.7
-
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index f9128e8e45..d459463322 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -102,6 +102,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 917df03b5b..87bf25452f 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -170,6 +170,58 @@
</section>
+<section><title>SSL 8.2.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct handling of empty server SNI extension</p>
+ <p>
+ Own Id: OTP-15168</p>
+ </item>
+ <item>
+ <p>
+ Correct cipher suite handling for ECDHE_*, the incorrect
+ handling could cause an incorrrect suite to be selected
+ and most likly fail the handshake.</p>
+ <p>
+ Own Id: OTP-15203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve cipher suite handling correcting ECC and TLS-1.2
+ requierments. Backport of solution for ERL-641</p>
+ <p>
+ Own Id: OTP-15178</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Option keyfile defaults to certfile and should be trumped
+ with key. This failed for engine keys.</p>
+ <p>
+ Own Id: OTP-15193</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 8.2.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -339,7 +391,7 @@
<p>
TLS sessions must be registered with SNI if provided, so
that sessions where client hostname verification would
- fail can not connect reusing a session created when the
+ fail cannot connect reusing a session created when the
server name verification succeeded.</p>
<p>
Own Id: OTP-14632</p>
@@ -517,7 +569,7 @@
public_key:pkix_verify_hostname/2 to verify the hostname
of the connection with the server certificates specified
hostname during certificate path validation. The user may
- explicitly disables it. Also if the hostname can not be
+ explicitly disables it. Also if the hostname cannot be
derived from the first argument to connect or is not
supplied by the server name indication option, the check
will not be performed.</p>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index e3deb1c8a4..6efa022a79 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -88,6 +88,7 @@
<p><c>| {client_preferred_next_protocols, {client | server,
[binary()]} | {client | server, [binary()], binary()}}</c></p>
<p><c>| {log_alert, boolean()}</c></p>
+ <p><c>| {log_level, atom()}</c></p>
<p><c>| {server_name_indication, hostname() | disable}</c></p>
<p><c>| {customize_hostname_check, list()}</c></p>
<p><c>| {sni_hosts, [{hostname(), [ssl_option()]}]}</c></p>
@@ -199,14 +200,14 @@
| sect163r1 | sect163r2 | secp160k1 | secp160r1 | secp160r2</c></p></item>
<tag><c>hello_extensions() =</c></tag>
- <item><p><c>#{renegotiation_info =>
+ <item><p><c>#{renegotiation_info => binary() | undefined,
signature_algs => [{hash(), ecsda| rsa| dsa}] | undefined
alpn => binary() | undefined,
- next_protocol_negotiation,
+ next_protocol_negotiation => binary() | undefined,
srp => string() | undefined,
- ec_point_formats ,
- elliptic_curves = [oid] | undefined
- sni = string()}
+ ec_point_formats => list() | undefined,
+ elliptic_curves => [oid] | undefined,
+ sni => string() | undefined}
}</c></p></item>
@@ -409,7 +410,7 @@ marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_valid
<item>check is only performed on the peer certificate.</item>
<tag><c>best_effort</c></tag>
- <item>if certificate revocation status can not be determined
+ <item>if certificate revocation status cannot be determined
it will be accepted as valid.</item>
</taglist>
@@ -796,7 +797,17 @@ fun(srp, Username :: string(), UserState :: term()) ->
the client.</p></item>
<tag><c>{log_alert, boolean()}</c></tag>
- <item><p>If set to <c>false</c>, error reports are not displayed.</p></item>
+ <item><p>If set to <c>false</c>, error reports are not displayed.</p>
+ <p>Deprecated in OTP 22, use <seealso marker="#log_level">log_level</seealso> instead.</p>
+ </item>
+
+ <tag><marker id="log_level"/><c>{log_level, atom()}</c></tag>
+ <item><p>Specifies the log level for TLS/DTLS. It can take the following
+ values (ordered by increasing verbosity level): <c>emergency, alert, critical, error,
+ warning, notice, info, debug.</c></p>
+ <p>At verbosity level <c>notice</c> and above error reports are
+ displayed in TLS. The level <c>debug</c> triggers verbose logging of TLS protocol
+ messages and logging of ignored alerts in DTLS.</p></item>
<tag><c>{honor_cipher_order, boolean()}</c></tag>
<item><p>If set to <c>true</c>, use the server preference for cipher
@@ -1066,7 +1077,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
</fsummary>
<type>
<v>SslSocket = sslsocket()</v>
- <v>Item = protocol | cipher_suite | sni_hostname | ecc | session_id | atom()</v>
+ <v>Item = protocol | selected_cipher_suite | sni_hostname | ecc | session_id | atom()</v>
<d>Meaningful atoms, not specified above, are the ssl option names.</d>
<v>Result = [{Item::atom(), Value::term()}]</v>
<v>Reason = term()</v>
@@ -1074,6 +1085,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
<desc><p>Returns the most relevant information about the connection, ssl options that
are undefined will be filtered out. Note that values that affect the security of the
connection will only be returned if explicitly requested by connection_information/2.</p>
+ <note><p>The legacy <c>Item = cipher_suite</c> is still supported
+ and returns the cipher suite on its (undocumented) legacy format.
+ It should be replaced by <c>selected_cipher_suite</c>.</p></note>
</desc>
</func>
@@ -1397,6 +1411,17 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
+ <name>set_log_level(Level) -> ok | {error, Reason}</name>
+ <fsummary>Sets log level for the SSL application.</fsummary>
+ <type>
+ <v>Level = atom()</v>
+ </type>
+ <desc>
+ <p>Sets log level for the SSL application.</p>
+ </desc>
+ </func>
+
+ <func>
<name>shutdown(SslSocket, How) -> ok | {error, Reason}</name>
<fsummary>Immediately closes a socket.</fsummary>
<type>
@@ -1513,9 +1538,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
to complete handshaking, that is,
establishing the SSL/TLS/DTLS connection.</p>
<warning>
- <p>The socket returned can only be used with
- <seealso marker="#handshake-2"> handshake/[2,3]</seealso>.
- No traffic can be sent or received before that call.</p>
+ <p>Most API functions require that the TLS/DTLS
+ connection is established to work as expected.
+ </p>
</warning>
<p>The accepted socket inherits the options set for
<c>ListenSocket</c> in
diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml
index e14f3f90dc..1774bd8f77 100644
--- a/lib/ssl/doc/src/ssl_distribution.xml
+++ b/lib/ssl/doc/src/ssl_distribution.xml
@@ -191,7 +191,7 @@ Eshell V5.0 (abort with ^G)
Any available SSL/TLS option can be specified in an options file,
but note that options that take a <c>fun()</c> has to use
the syntax <c>fun Mod:Func/Arity</c> since a function
- body can not be compiled when consulting a file.
+ body cannot be compiled when consulting a file.
</p>
<p>
Do not tamper with the socket options
diff --git a/lib/ssl/examples/src/client_server.erl b/lib/ssl/examples/src/client_server.erl
index c150f43bff..7a266f544d 100644
--- a/lib/ssl/examples/src/client_server.erl
+++ b/lib/ssl/examples/src/client_server.erl
@@ -39,15 +39,15 @@ start() ->
%% Accept
{ok, ASock} = ssl:transport_accept(LSock),
- ok = ssl:ssl_accept(ASock),
+ {ok, SslSocket} = ssl:handshake(ASock),
io:fwrite("Accept: accepted.~n"),
- {ok, Cert} = ssl:peercert(ASock),
+ {ok, Cert} = ssl:peercert(SslSocket),
io:fwrite("Accept: peer cert:~n~p~n", [public_key:pkix_decode_cert(Cert, otp)]),
io:fwrite("Accept: sending \"hello\".~n"),
- ssl:send(ASock, "hello"),
- {error, closed} = ssl:recv(ASock, 0),
+ ssl:send(SslSocket, "hello"),
+ {error, closed} = ssl:recv(SslSocket, 0),
io:fwrite("Accept: detected closed.~n"),
- ssl:close(ASock),
+ ssl:close(SslSocket),
io:fwrite("Listen: closing and terminating.~n"),
ssl:close(LSock),
@@ -75,7 +75,7 @@ mk_opts(Role) ->
[{active, false},
{verify, 2},
{depth, 2},
+ {server_name_indication, disable},
{cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
{certfile, filename:join([Dir, Role, "cert.pem"])},
{keyfile, filename:join([Dir, Role, "key.pem"])}].
-
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index ebcb511653..1db18d4e5a 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -86,7 +86,8 @@ MODULES= \
ssl_record \
ssl_v3 \
tls_v1 \
- dtls_v1
+ dtls_v1 \
+ ssl_logger
INTERNAL_HRL_FILES = \
ssl_alert.hrl ssl_cipher.hrl \
@@ -118,7 +119,7 @@ EXTRA_ERLC_FLAGS = +warn_unused_vars
ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
-pz $(EBIN) \
-pz $(ERL_TOP)/lib/public_key/ebin \
- $(EXTRA_ERLC_FLAGS) -DVSN=\"$(VSN)\"
+ $(EXTRA_ERLC_FLAGS)
# ----------------------------------------------------
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 53b46542e7..c0e81d6a28 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -32,6 +32,7 @@
-include("ssl_internal.hrl").
-include("ssl_srp.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Internal application API
@@ -91,13 +92,14 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
gen_statem:enter_loop(?MODULE, [], init, State)
catch
throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error,State0})
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
end.
%%====================================================================
%% State transition handling
@@ -470,7 +472,8 @@ init(Type, Event, State) ->
%%--------------------------------------------------------------------
error(enter, _, State) ->
{keep_state, State};
-error({call, From}, {start, _Timeout}, {Error, State}) ->
+error({call, From}, {start, _Timeout},
+ #state{protocol_specific = #{error := Error}} = State) ->
ssl_connection:stop_and_reply(
normal, {reply, From, {error, Error}}, State);
error({call, _} = Call, Msg, State) ->
@@ -926,7 +929,7 @@ handle_own_alert(Alert, Version, StateName, #state{data_tag = udp,
ssl_options = Options} = State0) ->
case ignore_alert(Alert, State0) of
{true, State} ->
- log_ignore_alert(Options#ssl_options.log_alert, StateName, Alert, Role),
+ log_ignore_alert(Options#ssl_options.log_level, StateName, Alert, Role),
{next_state, StateName, State};
{false, State} ->
ssl_connection:handle_own_alert(Alert, Version, StateName, State)
@@ -1123,9 +1126,9 @@ is_ignore_alert(#alert{description = ?ILLEGAL_PARAMETER}) ->
is_ignore_alert(_) ->
false.
-log_ignore_alert(true, StateName, Alert, Role) ->
+log_ignore_alert(debug, StateName, Alert, Role) ->
Txt = ssl_alert:alert_txt(Alert),
- error_logger:format("DTLS over UDP ~p: In state ~p ignored to send ALERT ~s as DoS-attack mitigation \n",
- [Role, StateName, Txt]);
-log_ignore_alert(false, _, _,_) ->
+ ?LOG_ERROR("DTLS over UDP ~p: In state ~p ignored to send ALERT ~s as DoS-attack mitigation \n",
+ [Role, StateName, Txt]);
+log_ignore_alert(_, _, _, _) ->
ok.
diff --git a/lib/ssl/src/dtls_packet_demux.erl b/lib/ssl/src/dtls_packet_demux.erl
index 1497c77cf3..e03a4e9cb9 100644
--- a/lib/ssl/src/dtls_packet_demux.erl
+++ b/lib/ssl/src/dtls_packet_demux.erl
@@ -24,6 +24,7 @@
-behaviour(gen_server).
-include("ssl_internal.hrl").
+-include_lib("kernel/include/logger.hrl").
%% API
-export([start_link/5, active_once/3, accept/2, sockname/1, close/1,
@@ -146,11 +147,11 @@ handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket
%% appears to make things work as expected!
handle_info({Error, Socket, econnreset = Error}, #state{listener = Socket, transport = {_,_,_, udp_error}} = State) ->
Report = io_lib:format("Ignore SSL UDP Listener: Socket error: ~p ~n", [Error]),
- error_logger:info_report(Report),
+ ?LOG_NOTICE(Report),
{noreply, State};
handle_info({Error, Socket, Error}, #state{listener = Socket, transport = {_,_,_, Error}} = State) ->
Report = io_lib:format("SSL Packet muliplxer shutdown: Socket error: ~p ~n", [Error]),
- error_logger:info_report(Report),
+ ?LOG_NOTICE(Report),
{noreply, State#state{close=true}};
handle_info({'DOWN', _, process, Pid, _}, #state{clients = Clients,
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index aa3d7e3f72..1194f4fc72 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -41,6 +41,7 @@
-include_lib("public_key/include/public_key.hrl").
-include("ssl_api.hrl").
+-include_lib("kernel/include/logger.hrl").
%% -------------------------------------------------------------------------
@@ -226,7 +227,7 @@ accept_loop(Driver, Listen, Kernel) ->
true ->
accept_loop(Driver, Listen, Kernel, Socket);
{false,IP} ->
- error_logger:error_msg(
+ ?LOG_ERROR(
"** Connection attempt from "
"disallowed IP ~w ** ~n", [IP]),
?shutdown2(no_node, trace({disallowed, IP}))
@@ -261,7 +262,7 @@ accept_loop(Driver, Listen, Kernel, Socket) ->
{error, {options, _}} = Error ->
%% Bad options: that's probably our fault.
%% Let's log that.
- error_logger:error_msg(
+ ?LOG_ERROR(
"Cannot accept TLS distribution connection: ~s~n",
[ssl:format_error(Error)]),
gen_tcp:close(Socket),
@@ -437,7 +438,7 @@ allowed_nodes(SslSocket, Allowed) ->
PeerCert, allowed_hosts(Allowed), PeerIP)
of
[] ->
- error_logger:error_msg(
+ ?LOG_ERROR(
"** Connection attempt from "
"disallowed node(s) ~p ** ~n", [PeerIP]),
?shutdown2(
@@ -691,12 +692,12 @@ split_node(Driver, Node, LongOrShortNames) ->
{node, Name, Host} ->
check_node(Driver, Node, Name, Host, LongOrShortNames);
{host, _} ->
- error_logger:error_msg(
+ ?LOG_ERROR(
"** Nodename ~p illegal, no '@' character **~n",
[Node]),
?shutdown2(Node, trace({illegal_node_n@me, Node}));
_ ->
- error_logger:error_msg(
+ ?LOG_ERROR(
"** Nodename ~p illegal **~n", [Node]),
?shutdown2(Node, trace({illegal_node_name, Node}))
end.
@@ -708,7 +709,7 @@ check_node(Driver, Node, Name, Host, LongOrShortNames) ->
{ok, _} ->
{Name, Host};
_ ->
- error_logger:error_msg(
+ ?LOG_ERROR(
"** System running to use "
"fully qualified hostnames **~n"
"** Hostname ~s is illegal **~n",
@@ -716,7 +717,7 @@ check_node(Driver, Node, Name, Host, LongOrShortNames) ->
?shutdown2(Node, trace({not_longnames, Host}))
end;
[_,_|_] when LongOrShortNames =:= shortnames ->
- error_logger:error_msg(
+ ?LOG_ERROR(
"** System NOT running to use "
"fully qualified hostnames **~n"
"** Hostname ~s is illegal **~n",
@@ -846,13 +847,13 @@ monitor_pid(Pid) ->
%% MRef = erlang:monitor(process, Pid),
%% receive
%% {'DOWN', MRef, _, _, normal} ->
- %% error_logger:error_report(
- %% [dist_proc_died,
+ %% ?LOG_ERROR(
+ %% [{slogan, dist_proc_died},
%% {reason, normal},
%% {pid, Pid}]);
%% {'DOWN', MRef, _, _, Reason} ->
- %% error_logger:info_report(
- %% [dist_proc_died,
+ %% ?LOG_NOTICE(
+ %% [{slogan, dist_proc_died},
%% {reason, Reason},
%% {pid, Pid}])
%% end
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index da281829cb..9679ea4687 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -51,6 +51,8 @@
ssl_crl_cache,
ssl_crl_cache_api,
ssl_crl_hash_dir,
+ %% Logging
+ ssl_logger,
%% App structure
ssl_app,
ssl_sup,
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 0f13b737ab..09953908ce 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -55,7 +55,8 @@
format_error/1, renegotiate/1, prf/5, negotiated_protocol/1,
connection_information/1, connection_information/2]).
%% Misc
--export([handle_options/2, tls_version/1, new_ssl_options/3, suite_to_str/1]).
+-export([handle_options/2, tls_version/1, new_ssl_options/3, suite_to_str/1,
+ set_log_level/1]).
-deprecated({ssl_accept, 1, eventually}).
-deprecated({ssl_accept, 2, eventually}).
@@ -87,6 +88,7 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
+
-spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
{error, reason()}.
-spec connect(host() | port(), [connect_option()] | inet:port_number(),
@@ -209,6 +211,8 @@ ssl_accept(Socket, SslOptions, Timeout) ->
%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
+
+%% Performs the SSL/TLS/DTLS server-side handshake.
handshake(ListenSocket) ->
handshake(ListenSocket, infinity).
@@ -216,6 +220,12 @@ handshake(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Tim
(Timeout == infinity) ->
ssl_connection:handshake(Socket, Timeout);
+%% If Socket is a ordinary socket(): upgrades a gen_tcp, or equivalent, socket to
+%% an SSL socket, that is, performs the SSL/TLS server-side handshake and returns
+%% the SSL socket.
+%%
+%% If Socket is an sslsocket(): provides extra SSL/TLS/DTLS options to those
+%% specified in ssl:listen/2 and then performs the SSL/TLS/DTLS handshake.
handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
handshake(ListenSocket, SslOptions, infinity).
@@ -792,6 +802,32 @@ suite_to_str(Cipher) ->
ssl_cipher:suite_to_str(Cipher).
+%%--------------------------------------------------------------------
+-spec set_log_level(atom()) -> ok | {error, term()}.
+%%
+%% Description: Set log level for the SSL application
+%%--------------------------------------------------------------------
+set_log_level(Level) ->
+ case application:get_all_key(ssl) of
+ {ok, PropList} ->
+ Modules = proplists:get_value(modules, PropList),
+ set_module_level(Modules, Level);
+ undefined ->
+ {error, ssl_not_started}
+ end.
+
+set_module_level(Modules, Level) ->
+ Fun = fun (Module) ->
+ ok = logger:set_module_level(Module, Level)
+ end,
+ try lists:map(Fun, Modules) of
+ _ ->
+ ok
+ catch
+ error:{badmatch, Error} ->
+ Error
+ end.
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -851,9 +887,10 @@ handle_options(Opts0, #ssl_options{protocol = Protocol, cacerts = CaCerts0,
[] ->
new_ssl_options(SslOpts1, NewVerifyOpts, RecordCB);
Value ->
- Versions = [RecordCB:protocol_version(Vsn) || Vsn <- Value],
+ Versions0 = [RecordCB:protocol_version(Vsn) || Vsn <- Value],
+ Versions1 = lists:sort(fun RecordCB:is_higher/2, Versions0),
new_ssl_options(proplists:delete(versions, SslOpts1),
- NewVerifyOpts#ssl_options{versions = Versions}, record_cb(Protocol))
+ NewVerifyOpts#ssl_options{versions = Versions1}, record_cb(Protocol))
end;
%% Handle all options in listen and connect
@@ -876,7 +913,8 @@ handle_options(Opts0, Role, Host) ->
[] ->
RecordCb:supported_protocol_versions();
Vsns ->
- [RecordCb:protocol_version(Vsn) || Vsn <- Vsns]
+ Versions0 = [RecordCb:protocol_version(Vsn) || Vsn <- Vsns],
+ lists:sort(fun RecordCb:is_higher/2, Versions0)
end,
Protocol = handle_option(protocol, Opts, tls),
@@ -888,7 +926,7 @@ handle_options(Opts0, Role, Host) ->
ok
end,
- SSLOptions = #ssl_options{
+ SSLOptions0 = #ssl_options{
versions = Versions,
verify = validate_option(verify, Verify),
verify_fun = VerifyFun,
@@ -935,7 +973,6 @@ handle_options(Opts0, Role, Host) ->
next_protocol_selector =
make_next_protocol_selector(
handle_option(client_preferred_next_protocols, Opts, undefined)),
- log_alert = handle_option(log_alert, Opts, true),
server_name_indication = handle_option(server_name_indication, Opts,
default_option_role(client,
server_name_indication_default(Host), Role)),
@@ -961,6 +998,10 @@ handle_options(Opts0, Role, Host) ->
handshake = handle_option(handshake, Opts, full),
customize_hostname_check = handle_option(customize_hostname_check, Opts, [])
},
+ LogLevel = handle_option(log_alert, Opts, true),
+ SSLOptions = SSLOptions0#ssl_options{
+ log_level = handle_option(log_level, Opts, LogLevel)
+ },
CbInfo = proplists:get_value(cb_info, Opts, default_cb_info(Protocol)),
SslOptions = [protocol, versions, verify, verify_fun, partial_chain,
@@ -972,7 +1013,7 @@ handle_options(Opts0, Role, Host) ->
cb_info, renegotiate_at, secure_renegotiate, hibernate_after,
erl_dist, alpn_advertised_protocols, sni_hosts, sni_fun,
alpn_preferred_protocols, next_protocols_advertised,
- client_preferred_next_protocols, log_alert,
+ client_preferred_next_protocols, log_alert, log_level,
server_name_indication, honor_cipher_order, padding_check, crl_check, crl_cache,
fallback, signature_algs, eccs, honor_ecc_order, beast_mitigation,
max_handshake_size, handshake, customize_hostname_check],
@@ -1151,7 +1192,20 @@ validate_option(client_preferred_next_protocols, {Precedence, PreferredProtocols
Value;
validate_option(client_preferred_next_protocols, undefined) ->
undefined;
-validate_option(log_alert, Value) when is_boolean(Value) ->
+validate_option(log_alert, true) ->
+ notice;
+validate_option(log_alert, false) ->
+ warning;
+validate_option(log_level, Value) when
+ is_atom(Value) andalso
+ (Value =:= emergency orelse
+ Value =:= alert orelse
+ Value =:= critical orelse
+ Value =:= error orelse
+ Value =:= warning orelse
+ Value =:= notice orelse
+ Value =:= info orelse
+ Value =:= debug) ->
Value;
validate_option(next_protocols_advertised, Value) when is_list(Value) ->
validate_binary_list(next_protocols_advertised, Value),
@@ -1259,7 +1313,8 @@ validate_binary_list(Opt, List) ->
end, List).
validate_versions([], Versions) ->
Versions;
-validate_versions([Version | Rest], Versions) when Version == 'tlsv1.2';
+validate_versions([Version | Rest], Versions) when Version == 'tlsv1.3';
+ Version == 'tlsv1.2';
Version == 'tlsv1.1';
Version == tlsv1;
Version == sslv3 ->
@@ -1272,10 +1327,11 @@ validate_versions([Ver| _], Versions) ->
tls_validate_versions([], Versions) ->
Versions;
-tls_validate_versions([Version | Rest], Versions) when Version == 'tlsv1.2';
- Version == 'tlsv1.1';
- Version == tlsv1;
- Version == sslv3 ->
+tls_validate_versions([Version | Rest], Versions) when Version == 'tlsv1.3';
+ Version == 'tlsv1.2';
+ Version == 'tlsv1.1';
+ Version == tlsv1;
+ Version == sslv3 ->
tls_validate_versions(Rest, Versions);
tls_validate_versions([Ver| _], Versions) ->
throw({error, {options, {Ver, {versions, Versions}}}}).
@@ -1526,8 +1582,10 @@ new_ssl_options([{next_protocols_advertised, Value} | Rest], #ssl_options{} = Op
new_ssl_options([{client_preferred_next_protocols, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
new_ssl_options(Rest, Opts#ssl_options{next_protocol_selector =
make_next_protocol_selector(validate_option(client_preferred_next_protocols, Value))}, RecordCB);
-new_ssl_options([{log_alert, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
- new_ssl_options(Rest, Opts#ssl_options{log_alert = validate_option(log_alert, Value)}, RecordCB);
+new_ssl_options([{log_alert, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#ssl_options{log_level = validate_option(log_alert, Value)}, RecordCB);
+new_ssl_options([{log_level, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
+ new_ssl_options(Rest, Opts#ssl_options{log_level = validate_option(log_level, Value)}, RecordCB);
new_ssl_options([{server_name_indication, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
new_ssl_options(Rest, Opts#ssl_options{server_name_indication = validate_option(server_name_indication, Value)}, RecordCB);
new_ssl_options([{honor_cipher_order, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl
index 62e8765d4a..2a5047c75c 100644
--- a/lib/ssl/src/ssl_app.erl
+++ b/lib/ssl/src/ssl_app.erl
@@ -29,9 +29,26 @@
-export([start/2, stop/1]).
start(_Type, _StartArgs) ->
+ start_logger(),
ssl_sup:start_link().
stop(_State) ->
+ stop_logger(),
ok.
+%%
+%% Description: Start SSL logger
+start_logger() ->
+ Config = #{level => debug,
+ filter_default => stop,
+ formatter => {ssl_logger, #{}}},
+ Filter = {fun logger_filters:domain/2,{log,sub,[otp,ssl]}},
+ logger:add_handler(ssl_handler, logger_std_h, Config),
+ logger:add_handler_filter(ssl_handler, filter_non_ssl, Filter).
+
+%%
+%% Description: Stop SSL logger
+stop_logger() ->
+ logger:remove_handler(ssl_handler).
+
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index c15e8a2138..017d18ee2c 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -69,7 +69,7 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) -
case SignedAndIssuerID of
{error, issuer_not_found} ->
- %% The root CA was not sent and can not be found.
+ %% The root CA was not sent and cannot be found.
handle_incomplete_chain(Path, PartialChainHandler);
{self, _} when length(Path) == 1 ->
{selfsigned_peer, Path};
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 754fc46404..07ec823829 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -187,7 +187,7 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
Mac, Fragment, {3, N})
- when N == 2; N == 3 ->
+ when N == 2; N == 3; N == 4 ->
NextIV = random_iv(IV),
L0 = build_cipher_block(BlockSz, Mac, Fragment),
L = [NextIV|L0],
@@ -320,6 +320,8 @@ suites({3, Minor}) ->
suites({_, Minor}) ->
dtls_v1:suites(Minor).
+all_suites({3, 4}) ->
+ all_suites({3, 3});
all_suites({3, _} = Version) ->
suites(Version)
++ chacha_suites(Version)
@@ -478,11 +480,12 @@ rc4_suites({3, Minor}) ->
rc4_suites(0) ->
[?TLS_RSA_WITH_RC4_128_SHA,
?TLS_RSA_WITH_RC4_128_MD5];
-rc4_suites(N) when N =< 3 ->
+rc4_suites(N) when N =< 4 ->
[?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDHE_RSA_WITH_RC4_128_SHA,
?TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDH_RSA_WITH_RC4_128_SHA].
+
%%--------------------------------------------------------------------
-spec des_suites(Version::ssl_record:ssl_version()) -> [cipher_suite()].
%%
@@ -517,13 +520,14 @@ rsa_suites(0) ->
?TLS_RSA_WITH_AES_128_CBC_SHA,
?TLS_RSA_WITH_3DES_EDE_CBC_SHA
];
-rsa_suites(N) when N =< 3 ->
+rsa_suites(N) when N =< 4 ->
[
?TLS_RSA_WITH_AES_256_GCM_SHA384,
?TLS_RSA_WITH_AES_256_CBC_SHA256,
?TLS_RSA_WITH_AES_128_GCM_SHA256,
?TLS_RSA_WITH_AES_128_CBC_SHA256
].
+
%%--------------------------------------------------------------------
-spec suite_definition(cipher_suite()) -> erl_cipher_suite().
%%
@@ -2430,7 +2434,7 @@ mac_hash({_,_}, ?NULL, _MacSecret, _SeqNo, _Type,
mac_hash({3, 0}, MacAlg, MacSecret, SeqNo, Type, Length, Fragment) ->
ssl_v3:mac_hash(MacAlg, MacSecret, SeqNo, Type, Length, Fragment);
mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment)
- when N =:= 1; N =:= 2; N =:= 3 ->
+ when N =:= 1; N =:= 2; N =:= 3; N =:= 4 ->
tls_v1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
Length, Fragment).
@@ -2635,7 +2639,7 @@ generic_block_cipher_from_bin({3, N}, T, IV, HashSize)
next_iv = IV};
generic_block_cipher_from_bin({3, N}, T, IV, HashSize)
- when N == 2; N == 3 ->
+ when N == 2; N == 3; N == 4 ->
Sz1 = byte_size(T) - 1,
<<_:Sz1/binary, ?BYTE(PadLength)>> = T,
IVLength = byte_size(IV),
@@ -2709,6 +2713,8 @@ filter_suites_pubkey(ec, Ciphers, _, OtpCert) ->
ec_ecdhe_suites(Ciphers)),
filter_keyuse_suites(keyAgreement, Uses, CiphersSuites, ec_ecdh_suites(Ciphers)).
+filter_suites_signature(rsa, Ciphers, {3, N}) when N >= 3 ->
+ Ciphers;
filter_suites_signature(rsa, Ciphers, Version) ->
(Ciphers -- ecdsa_signed_suites(Ciphers, Version)) -- dsa_signed_suites(Ciphers, Version);
filter_suites_signature(dsa, Ciphers, Version) ->
@@ -2775,6 +2781,8 @@ ecdsa_signed_suites(Ciphers, Version) ->
rsa_keyed(dhe_rsa) ->
true;
+rsa_keyed(ecdhe_rsa) ->
+ true;
rsa_keyed(rsa) ->
true;
rsa_keyed(rsa_psk) ->
@@ -2838,6 +2846,8 @@ ec_keyed(ecdh_ecdsa) ->
true;
ec_keyed(ecdh_rsa) ->
true;
+ec_keyed(ecdhe_ecdsa) ->
+ true;
ec_keyed(_) ->
false.
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index 63c0a416ef..1e6dab9276 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -91,9 +91,9 @@ init_certificates(undefined, #{pem_cache := PemCache} = Config, CertFile, server
end;
init_certificates(Cert, Config, _, _) ->
{ok, Config#{own_certificate => Cert}}.
-init_private_key(_, #{algorithm := Alg} = Key, <<>>, _Password, _Client) when Alg == ecdsa;
- Alg == rsa;
- Alg == dss ->
+init_private_key(_, #{algorithm := Alg} = Key, _, _Password, _Client) when Alg == ecdsa;
+ Alg == rsa;
+ Alg == dss ->
case maps:is_key(engine, Key) andalso maps:is_key(key_id, Key) of
true ->
Key;
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 556c204ab1..6e98baf984 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -35,6 +35,7 @@
-include("ssl_internal.hrl").
-include("ssl_srp.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Setup
@@ -334,14 +335,20 @@ handle_own_alert(Alert, Version, StateName,
connection_states = ConnectionStates,
ssl_options = SslOpts} = State) ->
try %% Try to tell the other side
- {BinMsg, _} =
- Connection:encode_alert(Alert, Version, ConnectionStates),
- Connection:send(Transport, Socket, BinMsg)
+ {BinMsg, _} =
+ Connection:encode_alert(Alert, Version, ConnectionStates),
+ Connection:send(Transport, Socket, BinMsg),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinMsg},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]})
catch _:_ -> %% Can crash if we are in a uninitialized state
ignore
end,
try %% Try to tell the local user
- log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), StateName, Alert#alert{role = Role}),
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName,
+ Alert#alert{role = Role}),
handle_normal_shutdown(Alert,StateName, State)
catch _:_ ->
ok
@@ -372,8 +379,9 @@ handle_alert(#alert{level = ?FATAL} = Alert, StateName,
port = Port, session = Session, user_application = {_Mon, Pid},
role = Role, socket_options = Opts, tracker = Tracker} = State) ->
invalidate_session(Role, Host, Port, Session),
- log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(),
- StateName, Alert#alert{role = opposite_role(Role)}),
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName,
+ Alert#alert{role = opposite_role(Role)}),
alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
stop(normal, State);
@@ -384,8 +392,9 @@ handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
#state{role = Role, ssl_options = SslOpts, protocol_cb = Connection, renegotiation = {true, internal}} = State) ->
- log_alert(SslOpts#ssl_options.log_alert, Role,
- Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName,
+ Alert#alert{role = opposite_role(Role)}),
handle_normal_shutdown(Alert, StateName, State),
stop({shutdown, peer_close}, State);
@@ -393,8 +402,9 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
#state{role = Role,
ssl_options = SslOpts, renegotiation = {true, From},
protocol_cb = Connection} = State0) ->
- log_alert(SslOpts#ssl_options.log_alert, Role,
- Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName,
+ Alert#alert{role = opposite_role(Role)}),
gen_statem:reply(From, {error, renegotiation_rejected}),
{Record, State1} = Connection:next_record(State0),
%% Go back to connection!
@@ -404,8 +414,9 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
%% Gracefully log and ignore all other warning alerts
handle_alert(#alert{level = ?WARNING} = Alert, StateName,
#state{ssl_options = SslOpts, protocol_cb = Connection, role = Role} = State0) ->
- log_alert(SslOpts#ssl_options.log_alert, Role,
- Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName,
+ Alert#alert{role = opposite_role(Role)}),
{Record, State} = Connection:next_record(State0),
Connection:next_event(StateName, Record, State).
@@ -419,7 +430,7 @@ write_application_data(Data0, {FromPid, _} = From,
transport_cb = Transport,
connection_states = ConnectionStates0,
socket_options = SockOpts,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State) ->
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt} = SslOpts} = State) ->
Data = encode_packet(Data0, SockOpts),
case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
@@ -430,16 +441,21 @@ write_application_data(Data0, {FromPid, _} = From,
{Msgs, ConnectionStates} =
Connection:encode_data(Data, Version, ConnectionStates0),
NewState = State#state{connection_states = ConnectionStates},
- case Connection:send(Transport, Socket, Msgs) of
- ok when FromPid =:= self() ->
- hibernate_after(connection, NewState, []);
- Error when FromPid =:= self() ->
- stop({shutdown, Error}, NewState);
- ok ->
- hibernate_after(connection, NewState, [{reply, From, ok}]);
- Result ->
- hibernate_after(connection, NewState, [{reply, From, Result}])
- end
+ RetVal = case Connection:send(Transport, Socket, Msgs) of
+ ok when FromPid =:= self() ->
+ hibernate_after(connection, NewState, []);
+ Error when FromPid =:= self() ->
+ stop({shutdown, Error}, NewState);
+ ok ->
+ hibernate_after(connection, NewState, [{reply, From, ok}]);
+ Result ->
+ hibernate_after(connection, NewState, [{reply, From, Result}])
+ end,
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => Msgs},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
+ RetVal
end.
read_application_data(Data, #state{user_application = {_Mon, Pid},
@@ -634,8 +650,10 @@ init(_Type, _Event, _State, _Connection) ->
tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-error({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, ?FUNCTION_NAME, State, Connection).
+error({call, From}, {close, _}, State, _Connection) ->
+ stop_and_reply(normal, {reply, From, ok}, State);
+error({call, From}, _Msg, State, _Connection) ->
+ {next_state, ?FUNCTION_NAME, State, [{reply, From, {error, closed}}]}.
%%--------------------------------------------------------------------
-spec hello(gen_statem:event_type(),
@@ -791,6 +809,7 @@ certify(internal, #server_key_exchange{exchange_keys = Keys},
#state{role = client, negotiated_version = Version,
key_algorithm = Alg,
public_key_info = PubKeyInfo,
+ session = Session,
connection_states = ConnectionStates} = State, Connection)
when Alg == dhe_dss; Alg == dhe_rsa;
Alg == ecdhe_rsa; Alg == ecdhe_ecdsa;
@@ -812,7 +831,8 @@ certify(internal, #server_key_exchange{exchange_keys = Keys},
ConnectionStates, ssl:tls_version(Version), PubKeyInfo) of
true ->
calculate_secret(Params#server_key_params.params,
- State#state{hashsign_algorithm = HashSign},
+ State#state{hashsign_algorithm = HashSign,
+ session = session_handle_params(Params#server_key_params.params, Session)},
Connection);
false ->
handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR),
@@ -1339,7 +1359,7 @@ handle_info({ErrorTag, Socket, econnaborted}, StateName,
handle_info({ErrorTag, Socket, Reason}, StateName, #state{socket = Socket,
error_tag = ErrorTag} = State) ->
Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]),
- error_logger:error_report(Report),
+ ?LOG_ERROR(Report),
handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
stop(normal, State);
@@ -1388,7 +1408,7 @@ handle_info({cancel_start_or_recv, _RecvFrom}, StateName, State) ->
handle_info(Msg, StateName, #state{socket = Socket, error_tag = Tag} = State) ->
Report = io_lib:format("SSL: Got unexpected info: ~p ~n", [{Msg, Tag, Socket}]),
- error_logger:info_report(Report),
+ ?LOG_NOTICE(Report),
{next_state, StateName, State}.
%%====================================================================
@@ -1472,7 +1492,7 @@ connection_info(#state{sni_hostname = SNIHostname,
RecordCB = record_cb(Connection),
CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher:suite_definition(CipherSuite),
IsNamedCurveSuite = lists:member(KexAlg,
- [ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdh_anon]),
+ [ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdhe_rsa, ecdh_anon]),
CurveInfo = case ECCCurve of
{namedCurve, Curve} when IsNamedCurveSuite ->
[{ecc, {named_curve, pubkey_cert_records:namedCurves(Curve)}}];
@@ -1482,6 +1502,7 @@ connection_info(#state{sni_hostname = SNIHostname,
[{protocol, RecordCB:protocol_version(Version)},
{session_id, SessionId},
{cipher_suite, ssl_cipher:erl_suite_definition(CipherSuiteDef)},
+ {selected_cipher_suite, CipherSuiteDef},
{sni_hostname, SNIHostname} | CurveInfo] ++ ssl_options_list(Opts).
security_info(#state{connection_states = ConnectionStates}) ->
@@ -1496,13 +1517,18 @@ do_server_hello(Type, #hello_extensions{next_protocol_negotiation = NextProtocol
ServerHelloExt,
#state{negotiated_version = Version,
session = #session{session_id = SessId},
- connection_states = ConnectionStates0}
+ connection_states = ConnectionStates0,
+ ssl_options = #ssl_options{versions = [HighestVersion|_]}}
= State0, Connection) when is_atom(Type) ->
-
+ %% TLS 1.3 - Section 4.1.3
+ %% Override server random values for TLS 1.3 downgrade protection mechanism.
+ ConnectionStates1 = update_server_random(ConnectionStates0, Version, HighestVersion),
+ State1 = State0#state{connection_states = ConnectionStates1},
ServerHello =
- ssl_handshake:server_hello(SessId, ssl:tls_version(Version), ConnectionStates0, ServerHelloExt),
+ ssl_handshake:server_hello(SessId, ssl:tls_version(Version),
+ ConnectionStates1, ServerHelloExt),
State = server_hello(ServerHello,
- State0#state{expecting_next_protocol_negotiation =
+ State1#state{expecting_next_protocol_negotiation =
NextProtocols =/= undefined}, Connection),
case Type of
new ->
@@ -1511,6 +1537,60 @@ do_server_hello(Type, #hello_extensions{next_protocol_negotiation = NextProtocol
resumed_server_hello(State, Connection)
end.
+update_server_random(#{pending_read := #{security_parameters := ReadSecParams0} =
+ ReadState0,
+ pending_write := #{security_parameters := WriteSecParams0} =
+ WriteState0} = ConnectionStates,
+ Version, HighestVersion) ->
+ ReadRandom = override_server_random(
+ ReadSecParams0#security_parameters.server_random,
+ Version,
+ HighestVersion),
+ WriteRandom = override_server_random(
+ WriteSecParams0#security_parameters.server_random,
+ Version,
+ HighestVersion),
+ ReadSecParams = ReadSecParams0#security_parameters{server_random = ReadRandom},
+ WriteSecParams = WriteSecParams0#security_parameters{server_random = WriteRandom},
+ ReadState = ReadState0#{security_parameters => ReadSecParams},
+ WriteState = WriteState0#{security_parameters => WriteSecParams},
+
+ ConnectionStates#{pending_read => ReadState, pending_write => WriteState}.
+
+%% TLS 1.3 - Section 4.1.3
+%%
+%% If negotiating TLS 1.2, TLS 1.3 servers MUST set the last eight bytes
+%% of their Random value to the bytes:
+%%
+%% 44 4F 57 4E 47 52 44 01
+%%
+%% If negotiating TLS 1.1 or below, TLS 1.3 servers MUST and TLS 1.2
+%% servers SHOULD set the last eight bytes of their Random value to the
+%% bytes:
+%%
+%% 44 4F 57 4E 47 52 44 00
+override_server_random(<<Random0:24/binary,_:8/binary>> = Random, {M,N}, {Major,Minor})
+ when Major > 3 orelse Major =:= 3 andalso Minor >= 4 -> %% TLS 1.3 or above
+ if M =:= 3 andalso N =:= 3 -> %% Negotating TLS 1.2
+ Down = ?RANDOM_OVERRIDE_TLS12,
+ <<Random0/binary,Down/binary>>;
+ M =:= 3 andalso N < 3 -> %% Negotating TLS 1.1 or prior
+ Down = ?RANDOM_OVERRIDE_TLS11,
+ <<Random0/binary,Down/binary>>;
+ true ->
+ Random
+ end;
+override_server_random(<<Random0:24/binary,_:8/binary>> = Random, {M,N}, {Major,Minor})
+ when Major =:= 3 andalso Minor =:= 3 -> %% TLS 1.2
+ if M =:= 3 andalso N < 3 -> %% Negotating TLS 1.1 or prior
+ Down = ?RANDOM_OVERRIDE_TLS11,
+ <<Random0/binary,Down/binary>>;
+ true ->
+ Random
+ end;
+override_server_random(Random, _, _) ->
+ Random.
+
new_server_hello(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression,
session_id = SessionId},
@@ -1575,11 +1655,9 @@ handle_peer_cert_key(client, _,
KeyAlg, #state{session = Session} = State) when KeyAlg == ecdh_rsa;
KeyAlg == ecdh_ecdsa ->
ECDHKey = public_key:generate_key(PublicKeyParams),
- {namedCurve, Oid} = PublicKeyParams,
- Curve = pubkey_cert_records:namedCurves(Oid), %% Need API function
PremasterSecret = ssl_handshake:premaster_secret(PublicKey, ECDHKey),
master_secret(PremasterSecret, State#state{diffie_hellman_keys = ECDHKey,
- session = Session#session{ecc = {named_curve, Curve}}});
+ session = Session#session{ecc = PublicKeyParams}});
%% We do currently not support cipher suites that use fixed DH.
%% If we want to implement that the following clause can be used
%% to extract DH parameters form cert.
@@ -1756,9 +1834,11 @@ key_exchange(#state{role = server, key_algorithm = Algo,
PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{diffie_hellman_keys = DHKeys};
-key_exchange(#state{role = server, private_key = Key, key_algorithm = Algo} = State, _)
+key_exchange(#state{role = server, private_key = #'ECPrivateKey'{parameters = ECCurve} = Key, key_algorithm = Algo,
+ session = Session} = State, _)
when Algo == ecdh_ecdsa; Algo == ecdh_rsa ->
- State#state{diffie_hellman_keys = Key};
+ State#state{diffie_hellman_keys = Key,
+ session = Session#session{ecc = ECCurve}};
key_exchange(#state{role = server, key_algorithm = Algo,
hashsign_algorithm = HashSignAlgo,
private_key = PrivateKey,
@@ -1914,12 +1994,13 @@ key_exchange(#state{role = client,
key_exchange(#state{role = client,
key_algorithm = Algorithm,
negotiated_version = Version,
- diffie_hellman_keys = Keys} = State0, Connection)
+ session = Session,
+ diffie_hellman_keys = #'ECPrivateKey'{parameters = ECCurve} = Key} = State0, Connection)
when Algorithm == ecdhe_ecdsa; Algorithm == ecdhe_rsa;
Algorithm == ecdh_ecdsa; Algorithm == ecdh_rsa;
Algorithm == ecdh_anon ->
- Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Keys}),
- Connection:queue_handshake(Msg, State0);
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Key}),
+ Connection:queue_handshake(Msg, State0#state{session = Session#session{ecc = ECCurve}});
key_exchange(#state{role = client,
ssl_options = SslOpts,
key_algorithm = psk,
@@ -2391,7 +2472,7 @@ handle_trusted_certs_db(#state{ssl_options =
handle_trusted_certs_db(#state{cert_db_ref = Ref,
cert_db = CertDb,
ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined ->
- %% Certs provided as DER directly can not be shared
+ %% Certs provided as DER directly cannot be shared
%% with other connections and it is safe to delete them when the connection ends.
ssl_pkix_db:remove_trusted_certs(Ref, CertDb);
handle_trusted_certs_db(#state{file_ref_db = undefined}) ->
@@ -2442,6 +2523,11 @@ cancel_timer(Timer) ->
erlang:cancel_timer(Timer),
ok.
+session_handle_params(#server_ecdh_params{curve = ECCurve}, Session) ->
+ Session#session{ecc = ECCurve};
+session_handle_params(_, Session) ->
+ Session.
+
register_session(client, Host, Port, #session{is_resumable = new} = Session0) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Host, Port, Session),
@@ -2522,7 +2608,7 @@ ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) ->
ssl_options_list(Keys, Values,
[{Key, lists:map(
fun(Suite) ->
- ssl_cipher:erl_suite_definition(Suite)
+ ssl_cipher:suite_definition(Suite)
end, Value)}
| Acc]);
ssl_options_list([Key | Keys], [Value | Values], Acc) ->
@@ -2739,14 +2825,14 @@ alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connectio
Transport, Socket, Connection, Tracker), ReasonCode})
end.
-log_alert(true, Role, ProtocolName, StateName, #alert{role = Role} = Alert) ->
+log_alert(Level, Role, ProtocolName, StateName, #alert{role = Role} = Alert) ->
Txt = ssl_alert:own_alert_txt(Alert),
- error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
-log_alert(true, Role, ProtocolName, StateName, Alert) ->
+ Report = io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]),
+ ssl_logger:notice(Level, Report);
+log_alert(Level, Role, ProtocolName, StateName, Alert) ->
Txt = ssl_alert:alert_txt(Alert),
- error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
-log_alert(false, _, _, _, _) ->
- ok.
+ Report = io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]),
+ ssl_logger:notice(Level, Report).
invalidate_session(client, Host, Port, Session) ->
ssl_manager:invalidate_session(Host, Port, Session);
@@ -2836,7 +2922,7 @@ erl_dist_stop_reason(
Reason, #state{ssl_options = #ssl_options{erl_dist = true}}) ->
case Reason of
normal ->
- %% We can not exit with normal since that will not bring
+ %% We cannot exit with normal since that will not bring
%% down the rest of the distribution processes
{shutdown, normal};
_ -> Reason
diff --git a/lib/ssl/src/ssl_crl_hash_dir.erl b/lib/ssl/src/ssl_crl_hash_dir.erl
index bb62737232..9478ff9b78 100644
--- a/lib/ssl/src/ssl_crl_hash_dir.erl
+++ b/lib/ssl/src/ssl_crl_hash_dir.erl
@@ -20,6 +20,7 @@
-module(ssl_crl_hash_dir).
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
-behaviour(ssl_crl_cache_api).
@@ -55,7 +56,7 @@ select(Issuer, {_DbHandle, [{dir, Dir}]}) ->
%% is happy with that, but if it's true, this is an error.
[];
{error, Error} ->
- error_logger:error_report(
+ ?LOG_ERROR(
[{cannot_find_crl, Error},
{dir, Dir},
{module, ?MODULE},
@@ -86,7 +87,7 @@ find_crls(Issuer, Hash, Dir, N, Acc) ->
error:Error ->
%% Something is wrong with the file. Report
%% it, and try the next one.
- error_logger:error_report(
+ ?LOG_ERROR(
[{crl_parse_error, Error},
{filename, Filename},
{module, ?MODULE},
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 3028ae9617..73757e6b65 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -53,7 +53,7 @@
-export([certify/7, certificate_verify/6, verify_signature/5,
master_secret/4, server_key_exchange_hash/2, verify_connection/6,
init_handshake_history/0, update_handshake_history/2, verify_server_key/5,
- select_version/3, extension_value/1
+ select_version/3, select_supported_version/2, extension_value/1
]).
%% Encode
@@ -505,6 +505,21 @@ verify_server_key(#server_key_params{params_bin = EncParams,
select_version(RecordCB, ClientVersion, Versions) ->
do_select_version(RecordCB, ClientVersion, Versions).
+
+%% Called by TLS 1.2/1.3 Server when "supported_versions" is present
+%% in ClientHello.
+%% Input lists are ordered (highest first)
+select_supported_version([], _ServerVersions) ->
+ undefined;
+select_supported_version([ClientVersion|T], ServerVersions) ->
+ case lists:member(ClientVersion, ServerVersions) of
+ true ->
+ ClientVersion;
+ false ->
+ select_supported_version(T, ServerVersions)
+ end.
+
+
%%====================================================================
%% Encode handshake
%%====================================================================
@@ -632,7 +647,20 @@ encode_hello_extensions([#sni{hostname = Hostname} | Rest], Acc) ->
?UINT16(ServerNameLength),
?BYTE(?SNI_NAMETYPE_HOST_NAME),
?UINT16(HostLen), HostnameBin/binary,
- Acc/binary>>).
+ Acc/binary>>);
+encode_hello_extensions([#client_hello_versions{versions = Versions0} | Rest], Acc) ->
+ Versions = encode_versions(Versions0),
+ VerLen = byte_size(Versions),
+ Len = VerLen + 2,
+ encode_hello_extensions(Rest, <<?UINT16(?SUPPORTED_VERSIONS_EXT),
+ ?UINT16(Len), ?UINT16(VerLen), Versions/binary, Acc/binary>>);
+encode_hello_extensions([#server_hello_selected_version{selected_version = Version0} | Rest], Acc) ->
+ Version = encode_versions(Version0),
+ Len = byte_size(Version), %% 2
+ encode_hello_extensions(Rest, <<?UINT16(?SUPPORTED_VERSIONS_EXT),
+ ?UINT16(Len), Version/binary, Acc/binary>>).
+
+
encode_client_protocol_negotiation(undefined, _) ->
undefined;
@@ -930,7 +958,8 @@ premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
%%====================================================================
client_hello_extensions(Version, CipherSuites,
#ssl_options{signature_algs = SupportedHashSigns,
- eccs = SupportedECCs} = SslOpts, ConnectionStates, Renegotiation) ->
+ eccs = SupportedECCs,
+ versions = Versions} = SslOpts, ConnectionStates, Renegotiation) ->
{EcPointFormats, EllipticCurves} =
case advertises_ec_ciphers(lists:map(fun ssl_cipher:suite_definition/1, CipherSuites)) of
true ->
@@ -940,18 +969,29 @@ client_hello_extensions(Version, CipherSuites,
end,
SRP = srp_user(SslOpts),
- #hello_extensions{
- renegotiation_info = renegotiation_info(tls_record, client,
- ConnectionStates, Renegotiation),
- srp = SRP,
- signature_algs = available_signature_algs(SupportedHashSigns, Version),
- ec_point_formats = EcPointFormats,
- elliptic_curves = EllipticCurves,
- alpn = encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
- next_protocol_negotiation =
- encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
- Renegotiation),
- sni = sni(SslOpts#ssl_options.server_name_indication)}.
+ HelloExtensions =
+ #hello_extensions{
+ renegotiation_info = renegotiation_info(tls_record, client,
+ ConnectionStates, Renegotiation),
+ srp = SRP,
+ signature_algs = available_signature_algs(SupportedHashSigns, Version),
+ ec_point_formats = EcPointFormats,
+ elliptic_curves = EllipticCurves,
+ alpn = encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
+ next_protocol_negotiation =
+ encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
+ Renegotiation),
+ sni = sni(SslOpts#ssl_options.server_name_indication)},
+
+ %% Add "supported_versions" extension if TLS 1.3
+ case Version of
+ {3,4} ->
+ HelloExtensions#hello_extensions{
+ client_hello_versions = #client_hello_versions{
+ versions = Versions}};
+ _Else ->
+ HelloExtensions
+ end.
handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
#hello_extensions{renegotiation_info = Info,
@@ -1055,7 +1095,8 @@ select_curve(undefined, _, _) ->
%%--------------------------------------------------------------------
select_hashsign(_, _, KeyExAlgo, _, _Version) when KeyExAlgo == dh_anon;
KeyExAlgo == ecdh_anon;
- KeyExAlgo == srp_anon ->
+ KeyExAlgo == srp_anon;
+ KeyExAlgo == psk ->
{null, anon};
%% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have
%% negotiated a lower version.
@@ -1064,17 +1105,14 @@ select_hashsign(HashSigns, Cert, KeyExAlgo,
select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version);
select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns,
{Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
- #'OTPCertificate'{tbsCertificate = TBSCert,
- signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
#'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
- Sign = sign_algo(SignAlgo),
SubSign = sign_algo(SubjAlgo),
case lists:filter(fun({_, S} = Algos) when S == SubSign ->
- is_acceptable_hash_sign(Algos, Sign,
- SubSign, KeyExAlgo, SupportedHashSigns);
+ is_acceptable_hash_sign(Algos, KeyExAlgo, SupportedHashSigns);
(_) ->
false
end, HashSigns) of
@@ -1724,6 +1762,16 @@ encode_alpn(undefined, _) ->
encode_alpn(Protocols, _) ->
#alpn{extension_data = lists:foldl(fun encode_protocol/2, <<>>, Protocols)}.
+
+encode_versions(Versions) ->
+ encode_versions(lists:reverse(Versions), <<>>).
+%%
+encode_versions([], Acc) ->
+ Acc;
+encode_versions([{M,N}|T], Acc) ->
+ encode_versions(T, <<?BYTE(M),?BYTE(N),Acc/binary>>).
+
+
hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo,
srp = SRP,
signature_algs = HashSigns,
@@ -1731,9 +1779,13 @@ hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo,
elliptic_curves = EllipticCurves,
alpn = ALPN,
next_protocol_negotiation = NextProtocolNegotiation,
- sni = Sni}) ->
+ sni = Sni,
+ client_hello_versions = Versions,
+ server_hello_selected_version = Version}) ->
[Ext || Ext <- [RenegotiationInfo, SRP, HashSigns,
- EcPointFormats, EllipticCurves, ALPN, NextProtocolNegotiation, Sni], Ext =/= undefined].
+ EcPointFormats, EllipticCurves, ALPN,
+ NextProtocolNegotiation, Sni,
+ Versions, Version], Ext =/= undefined].
%%-------------Decode handshakes---------------------------------
dec_server_key(<<?UINT16(PLen), P:PLen/binary,
@@ -1933,15 +1985,28 @@ dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len),
ECPointFormats}});
dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), Rest/binary>>, Acc) when Len == 0 ->
- dec_hello_extensions(Rest, Acc#hello_extensions{sni = ""}); %% Server may send an empy SNI
+ dec_hello_extensions(Rest, Acc#hello_extensions{sni = #sni{hostname = ""}}); %% Server may send an empy SNI
dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Acc) ->
<<?UINT16(_), NameList/binary>> = ExtData,
dec_hello_extensions(Rest, Acc#hello_extensions{sni = dec_sni(NameList)});
+
+dec_hello_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>, Acc) when Len > 2 ->
+ <<?UINT16(_),Versions/binary>> = ExtData,
+ dec_hello_extensions(Rest, Acc#hello_extensions{
+ client_hello_versions =
+ #client_hello_versions{versions = decode_versions(Versions)}});
+
+dec_hello_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
+ ?UINT16(Version), Rest/binary>>, Acc) when Len =:= 2, Version =:= 16#0304 ->
+ dec_hello_extensions(Rest, Acc#hello_extensions{
+ server_hello_selected_version =
+ #server_hello_selected_version{selected_version = [{3,4}]}});
+
%% Ignore data following the ClientHello (i.e.,
%% extensions) if not understood.
-
dec_hello_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Acc) ->
dec_hello_extensions(Rest, Acc);
%% This theoretically should not happen if the protocol is followed, but if it does it is ignored.
@@ -1963,6 +2028,15 @@ decode_alpn(undefined) ->
decode_alpn(#alpn{extension_data=Data}) ->
decode_protocols(Data, []).
+decode_versions(Versions) ->
+ decode_versions(Versions, []).
+%%
+decode_versions(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_versions(<<?BYTE(M),?BYTE(N),Rest/binary>>, Acc) ->
+ decode_versions(Rest, [{M,N}|Acc]).
+
+
decode_next_protocols({next_protocol_negotiation, Protocols}) ->
decode_protocols(Protocols, []).
@@ -2231,37 +2305,7 @@ sign_algo(Alg) ->
{_, Sign} =public_key:pkix_sign_types(Alg),
Sign.
-is_acceptable_hash_sign(Algos, _, _, KeyExAlgo, SupportedHashSigns) when
- KeyExAlgo == dh_dss;
- KeyExAlgo == dh_rsa;
- KeyExAlgo == ecdh_rsa;
- KeyExAlgo == ecdh_ecdsa
- ->
- %% *dh_* could be called only *dh in TLS-1.2
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign(Algos, rsa, ecdsa, ecdhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, dhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, ecdhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, srp_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, rsa_psk, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, dhe_dss, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, srp_dss, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, _, dhe_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdh_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdhe_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when
+is_acceptable_hash_sign( _, KeyExAlgo, _) when
KeyExAlgo == psk;
KeyExAlgo == dhe_psk;
KeyExAlgo == ecdhe_psk;
@@ -2270,8 +2314,9 @@ is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when
KeyExAlgo == ecdhe_anon
->
true;
-is_acceptable_hash_sign(_,_,_,_,_) ->
- false.
+is_acceptable_hash_sign(Algos,_, SupportedHashSigns) ->
+ is_acceptable_hash_sign(Algos, SupportedHashSigns).
+
is_acceptable_hash_sign(Algos, SupportedHashSigns) ->
lists:member(Algos, SupportedHashSigns).
@@ -2464,13 +2509,7 @@ cert_curve(Cert, ECCCurve0, CipherSuite) ->
#'OTPSubjectPublicKeyInfo'{algorithm = AlgInfo}
= TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
{namedCurve, Oid} = AlgInfo#'PublicKeyAlgorithm'.parameters,
- try pubkey_cert_records:namedCurves(Oid) of
- Curve ->
- {{named_curve, Curve}, CipherSuite}
- catch
- _:_ ->
- {no_curve, no_suite}
- end;
+ {{namedCurve, Oid}, CipherSuite};
_ ->
{ECCCurve0, CipherSuite}
end.
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index a191fcf766..9cc6f570fc 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -105,7 +105,9 @@
srp,
ec_point_formats,
elliptic_curves,
- sni
+ sni,
+ client_hello_versions,
+ server_hello_selected_version
}).
-record(server_hello, {
@@ -377,4 +379,13 @@
hostname = undefined
}).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Supported Versions TLS 1.3 section 4.2.1
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(SUPPORTED_VERSIONS_EXT, 43).
+
+-record(client_hello_versions, {versions}).
+-record(server_hello_selected_version, {selected_version}).
+
-endif. % -ifdef(ssl_handshake).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index ae1c3ea47c..0d3093c1ae 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -25,6 +25,7 @@
-include_lib("public_key/include/public_key.hrl").
+-define(VSN, "8.2.6").
-define(SECRET_PRINTOUT, "***").
-type reason() :: term().
@@ -71,14 +72,39 @@
-define(FALSE, 1).
%% sslv3 is considered insecure due to lack of padding check (Poodle attack)
-%% Keep as interop with legacy software but do not support as default
--define(ALL_AVAILABLE_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
+%% Keep as interop with legacy software but do not support as default
+%% tlsv1.3 is under development (experimental).
+-define(ALL_AVAILABLE_VERSIONS, ['tlsv1.3', 'tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
-define(ALL_AVAILABLE_DATAGRAM_VERSIONS, ['dtlsv1.2', dtlsv1]).
+%% Defines the default versions when not specified by an ssl option.
-define(ALL_SUPPORTED_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1]).
-define(MIN_SUPPORTED_VERSIONS, ['tlsv1.1', tlsv1]).
+
+%% Versions allowed in TLSCiphertext.version (TLS 1.2 and prior) and
+%% TLSCiphertext.legacy_record_version (TLS 1.3).
+%% TLS 1.3 sets TLSCiphertext.legacy_record_version to 0x0303 for all records
+%% generated other than an than an initial ClientHello, where it MAY also be 0x0301.
+%% Thus, the allowed range is limited to 0x0300 - 0x0303.
+-define(ALL_TLS_RECORD_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
+
-define(ALL_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
-define(MIN_DATAGRAM_SUPPORTED_VERSIONS, [dtlsv1]).
+%% TLS 1.3 - Section 4.1.3
+%%
+%% If negotiating TLS 1.2, TLS 1.3 servers MUST set the last eight bytes
+%% of their Random value to the bytes:
+%%
+%% 44 4F 57 4E 47 52 44 01
+%%
+%% If negotiating TLS 1.1 or below, TLS 1.3 servers MUST and TLS 1.2
+%% servers SHOULD set the last eight bytes of their Random value to the
+%% bytes:
+%%
+%% 44 4F 57 4E 47 52 44 00
+-define(RANDOM_OVERRIDE_TLS12, <<16#44,16#4F,16#57,16#4E,16#47,16#52,16#44,16#01>>).
+-define(RANDOM_OVERRIDE_TLS11, <<16#44,16#4F,16#57,16#4E,16#47,16#52,16#44,16#00>>).
+
-define('24H_in_msec', 86400000).
-define('24H_in_sec', 86400).
@@ -127,7 +153,7 @@
alpn_preferred_protocols = undefined :: [binary()] | undefined,
next_protocols_advertised = undefined :: [binary()] | undefined,
next_protocol_selector = undefined, %% fun([binary()]) -> binary())
- log_alert :: boolean(),
+ log_level = notice :: atom(),
server_name_indication = undefined,
sni_hosts :: [{inet:hostname(), [tuple()]}],
sni_fun :: function() | undefined,
@@ -180,6 +206,8 @@
-type gen_fsm_state_return() :: {next_state, state_name(), term()} |
{next_state, state_name(), term(), timeout()} |
{stop, term(), term()}.
+-type ssl_options() :: #ssl_options{}.
+
-endif. % -ifdef(ssl_internal).
diff --git a/lib/ssl/src/ssl_logger.erl b/lib/ssl/src/ssl_logger.erl
new file mode 100644
index 0000000000..35c8dcfd48
--- /dev/null
+++ b/lib/ssl/src/ssl_logger.erl
@@ -0,0 +1,349 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ssl_logger).
+
+-export([debug/3,
+ format/2,
+ notice/2]).
+
+-define(DEC2HEX(X),
+ if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0;
+ ((X) >= 10) andalso ((X) =< 15) -> (X) + $a - 10
+ end).
+
+-define(rec_info(T,R),lists:zip(record_info(fields,T),tl(tuple_to_list(R)))).
+
+-include("tls_record.hrl").
+-include("ssl_internal.hrl").
+-include("tls_handshake.hrl").
+-include_lib("kernel/include/logger.hrl").
+
+%%-------------------------------------------------------------------------
+%% External API
+%%-------------------------------------------------------------------------
+
+%% SSL log formatter
+format(#{level:= _Level, msg:= {report, Msg}, meta:= _Meta}, _Config0) ->
+ #{direction := Direction,
+ protocol := Protocol,
+ message := BinMsg0} = Msg,
+ case Protocol of
+ 'tls_record' ->
+ BinMsg = lists:flatten(BinMsg0),
+ format_tls_record(Direction, BinMsg);
+ 'handshake' ->
+ format_handshake(Direction, BinMsg0);
+ _Other ->
+ []
+ end.
+
+%% Stateful logging
+debug(Level, Report, Meta) ->
+ case logger:compare_levels(Level, debug) of
+ lt ->
+ ?LOG_DEBUG(Report, Meta);
+ eq ->
+ ?LOG_DEBUG(Report, Meta);
+ _ ->
+ ok
+ end.
+
+%% Stateful logging
+notice(Level, Report) ->
+ case logger:compare_levels(Level, notice) of
+ lt ->
+ ?LOG_NOTICE(Report);
+ eq ->
+ ?LOG_NOTICE(Report);
+ _ ->
+ ok
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Handshake Protocol
+%%-------------------------------------------------------------------------
+format_handshake(Direction, BinMsg) ->
+ {Header, Message} = parse_handshake(Direction, BinMsg),
+ io_lib:format("~s~n~s~n", [Header, Message]).
+
+
+parse_handshake(Direction, #client_hello{
+ client_version = Version
+ } = ClientHello) ->
+ Header = io_lib:format("~s ~s Handshake, ClientHello",
+ [header_prefix(Direction),
+ version(Version)]),
+ Message = io_lib:format("~p", [?rec_info(client_hello, ClientHello)]),
+ {Header, Message};
+parse_handshake(Direction, #server_hello{
+ server_version = Version
+ } = ServerHello) ->
+ Header = io_lib:format("~s ~s Handshake, ServerHello",
+ [header_prefix(Direction),
+ version(Version)]),
+ Message = io_lib:format("~p", [?rec_info(server_hello, ServerHello)]),
+ {Header, Message};
+parse_handshake(Direction, #certificate{} = Certificate) ->
+ Header = io_lib:format("~s Handshake, Certificate",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(certificate, Certificate)]),
+ {Header, Message};
+parse_handshake(Direction, #server_key_exchange{} = ServerKeyExchange) ->
+ Header = io_lib:format("~s Handshake, ServerKeyExchange",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(server_key_exchange, ServerKeyExchange)]),
+ {Header, Message};
+parse_handshake(Direction, #server_key_params{} = ServerKeyExchange) ->
+ Header = io_lib:format("~s Handshake, ServerKeyExchange",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(server_key_params, ServerKeyExchange)]),
+ {Header, Message};
+parse_handshake(Direction, #certificate_request{} = CertificateRequest) ->
+ Header = io_lib:format("~s Handshake, CertificateRequest",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(certificate_request, CertificateRequest)]),
+ {Header, Message};
+parse_handshake(Direction, #server_hello_done{} = ServerHelloDone) ->
+ Header = io_lib:format("~s Handshake, ServerHelloDone",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(server_hello_done, ServerHelloDone)]),
+ {Header, Message};
+parse_handshake(Direction, #client_key_exchange{} = ClientKeyExchange) ->
+ Header = io_lib:format("~s Handshake, ClientKeyExchange",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(client_key_exchange, ClientKeyExchange)]),
+ {Header, Message};
+parse_handshake(Direction, #certificate_verify{} = CertificateVerify) ->
+ Header = io_lib:format("~s Handshake, CertificateVerify",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(certificate_verify, CertificateVerify)]),
+ {Header, Message};
+parse_handshake(Direction, #finished{} = Finished) ->
+ Header = io_lib:format("~s Handshake, Finished",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(finished, Finished)]),
+ {Header, Message};
+parse_handshake(Direction, #hello_request{} = HelloRequest) ->
+ Header = io_lib:format("~s Handshake, HelloRequest",
+ [header_prefix(Direction)]),
+ Message = io_lib:format("~p", [?rec_info(hello_request, HelloRequest)]),
+ {Header, Message}.
+
+
+version({3,3}) ->
+ "TLS 1.2";
+version({3,2}) ->
+ "TLS 1.1";
+version({3,1}) ->
+ "TLS 1.0";
+version({3,0}) ->
+ "SSL 3.0";
+version({M,N}) ->
+ io_lib:format("TLS [0x0~B0~B]", [M,N]).
+
+
+header_prefix(inbound) ->
+ "<<<";
+header_prefix(outbound) ->
+ ">>>".
+
+
+%%-------------------------------------------------------------------------
+%% TLS Record Protocol
+%%-------------------------------------------------------------------------
+format_tls_record(Direction, BinMsg) ->
+ {Message, Size} = convert_to_hex('tls_record', BinMsg),
+ Header = io_lib:format("~s (~B bytes) ~s~n",
+ [header_prefix_tls_record(Direction),
+ Size,
+ tls_record_version(BinMsg)]),
+ Header ++ Message.
+
+
+header_prefix_tls_record(inbound) ->
+ "reading";
+header_prefix_tls_record(outbound) ->
+ "writing".
+
+
+tls_record_version([<<?BYTE(B),?BYTE(3),?BYTE(3),_/binary>>|_]) ->
+ io_lib:format("TLS 1.2 Record Protocol, ~s", [msg_type(B)]);
+tls_record_version([<<?BYTE(B),?BYTE(3),?BYTE(2),_/binary>>|_]) ->
+ io_lib:format("TLS 1.1 Record Protocol, ~s", [msg_type(B)]);
+tls_record_version([<<?BYTE(B),?BYTE(3),?BYTE(1),_/binary>>|_]) ->
+ io_lib:format("TLS 1.0 Record Protocol, ~s", [msg_type(B)]);
+tls_record_version([<<?BYTE(B),?BYTE(3),?BYTE(0),_/binary>>|_]) ->
+ io_lib:format("SSL 3.0 Record Protocol, ~s", [msg_type(B)]);
+tls_record_version([<<?BYTE(B),?BYTE(M),?BYTE(N),_/binary>>|_]) ->
+ io_lib:format("TLS [0x0~B0~B] Record Protocol, ~s", [M, N, msg_type(B)]).
+
+
+msg_type(20) -> "change_cipher_spec";
+msg_type(21) -> "alert";
+msg_type(22) -> "handshake";
+msg_type(23) -> "application_data";
+msg_type(_) -> unknown.
+
+
+%%-------------------------------------------------------------------------
+%% Hex encoding functions
+%%-------------------------------------------------------------------------
+convert_to_hex(Protocol, BinMsg) ->
+ convert_to_hex(Protocol, BinMsg, [], [], 0).
+%%
+convert_to_hex(P, [], Row0, Acc, C) when C rem 16 =:= 0 ->
+ Row = lists:reverse(end_row(P, Row0)),
+ {lists:reverse(Acc) ++ Row ++ io_lib:nl(), C};
+convert_to_hex(P, [], Row0, Acc, C) ->
+ Row = lists:reverse(end_row(P, Row0)),
+ Padding = calculate_padding(Row0, Acc),
+ PaddedRow = string:pad(Row, Padding, leading, $ ),
+ {lists:reverse(Acc) ++ PaddedRow ++ io_lib:nl(), C};
+convert_to_hex(P, [H|T], Row, Acc, C) when is_list(H) ->
+ convert_to_hex(P, H ++ T, Row, Acc, C);
+convert_to_hex(P, [<<>>|T], Row, Acc, C) ->
+ convert_to_hex(P, T, Row, Acc, C);
+
+%% First line
+convert_to_hex(P, [<<A:4,B:4,R/binary>>|T], Row, Acc, C) when C =:= 0 ->
+ convert_to_hex(P, [<<R/binary>>|T],
+ update_row(<<A:4,B:4>>, Row),
+ prepend_first_row(P, A, B, Acc, C),
+ C + 1);
+%% New line
+convert_to_hex(P, [<<A:4,B:4,R/binary>>|T], Row, Acc, C) when C rem 16 =:= 0 ->
+ convert_to_hex(P, [<<R/binary>>|T],
+ update_row(<<A:4,B:4>>, []),
+ prepend_row(P, A, B, Row, Acc, C),
+ C + 1);
+%% Add 8th hex with extra whitespace
+%% 0000 - 16 03 02 00 bd 01 00 00 b9 ...
+%% ^^^^
+convert_to_hex(P, [<<A:4,B:4,R/binary>>|T], Row, Acc, C) when C rem 8 =:= 7 ->
+ convert_to_hex(P, [<<R/binary>>|T],
+ update_row(<<A:4,B:4>>, Row),
+ prepend_eighths_hex(A, B, Acc),
+ C + 1);
+convert_to_hex(P, [<<A:4,B:4,R/binary>>|T], Row, Acc, C) ->
+ convert_to_hex(P, [<<R/binary>>|T],
+ update_row(<<A:4,B:4>>, Row),
+ prepend_hex(A, B, Acc),
+ C + 1);
+%% First line
+convert_to_hex(P, [H|T], Row, Acc, C) when is_integer(H), C =:= 0 ->
+ convert_to_hex(P, T,
+ update_row(H, Row),
+ prepend_first_row(P, H, Acc, C),
+ C + 1);
+%% New line
+convert_to_hex(P, [H|T], Row, Acc, C) when is_integer(H), C rem 16 =:= 0 ->
+ convert_to_hex(P, T,
+ update_row(H, []),
+ prepend_row(P, H, Row, Acc, C),
+ C + 1);
+%% Add 8th hex with extra whitespace
+%% 0000 - 16 03 02 00 bd 01 00 00 b9 ...
+%% ^^^^
+convert_to_hex(P, [H|T], Row, Acc, C) when is_integer(H), C rem 8 =:= 7 ->
+ convert_to_hex(P, T,
+ update_row(H, Row),
+ prepend_eighths_hex(H, Acc),
+ C + 1);
+convert_to_hex(P, [H|T], Row, Acc, C) when is_integer(H) ->
+ convert_to_hex(P, T,
+ update_row(H, Row),
+ prepend_hex(H, Acc),
+ C + 1).
+
+
+row_prefix(tls_record, N) ->
+ S = string:pad(string:to_lower(erlang:integer_to_list(N, 16)),4,leading,$0),
+ lists:reverse(lists:flatten(S ++ " - ")).
+
+
+end_row(tls_record, Row) ->
+ Row ++ " ".
+
+
+%% Calculate padding of the "printable character" lines in order to be
+%% visually aligned.
+calculate_padding(Row, Acc) ->
+ %% Number of new line characters
+ NNL = (length(Acc) div 75) * length(io_lib:nl()),
+ %% Length of the last printed line
+ Length = (length(Acc) - NNL) rem 75,
+ %% Adjusted length of the last printed line
+ PaddedLength = 75 - (16 - length(Row)), %% Length
+ %% Padding
+ PaddedLength - Length.
+
+
+%%-------------------------------------------------------------------------
+%% Functions operating on reversed lists
+%%-------------------------------------------------------------------------
+update_row(B, Row) when is_binary(B) ->
+ case binary_to_list(B) of
+ [C] when 32 =< C, C =< 126 ->
+ [C|Row];
+ _Else ->
+ [$.|Row]
+ end;
+update_row(C, Row) when 32 =< C, C =< 126 ->
+ [C|Row];
+update_row(_, Row) ->
+ [$.|Row].
+
+
+prepend_first_row(P, A, B, Acc, C) ->
+ prepend_hex(A, B,row_prefix(P, C) ++ Acc).
+%%
+prepend_first_row(P, N, Acc, C) ->
+ prepend_hex(N,row_prefix(P, C) ++ Acc).
+
+prepend_row(P, A, B, Row, Acc, C) ->
+ prepend_hex(A, B,row_prefix(P, C) ++ io_lib:nl() ++ end_row(P, Row) ++ Acc).
+%%
+prepend_row(P, N, Row, Acc, C) ->
+ prepend_hex(N,row_prefix(P, C) ++ io_lib:nl() ++ end_row(P, Row) ++ Acc).
+
+
+
+prepend_hex(A, B, Acc) ->
+ [$ ,?DEC2HEX(B),?DEC2HEX(A)|Acc].
+%%
+prepend_hex(N, Acc) ->
+ " " ++ number_to_hex(N) ++ Acc.
+
+
+prepend_eighths_hex(A, B, Acc) ->
+ [$ ,$ ,?DEC2HEX(B),?DEC2HEX(A)|Acc].
+%%
+prepend_eighths_hex(N, Acc) ->
+ " " ++ number_to_hex(N) ++ Acc.
+
+number_to_hex(N) ->
+ case string:to_lower(erlang:integer_to_list(N, 16)) of
+ H when length(H) < 2 ->
+ lists:append(H, "0");
+ H ->
+ lists:reverse(H)
+ end.
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index f44fe6a2bf..b3a425b2fe 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -127,7 +127,13 @@ cache_pem_file(File, DbHandle) ->
[Content] ->
{ok, Content};
undefined ->
- ssl_pem_cache:insert(File)
+ case ssl_pkix_db:decode_pem_file(File) of
+ {ok, Content} ->
+ ssl_pem_cache:insert(File, Content),
+ {ok, Content};
+ Error ->
+ Error
+ end
end.
%%--------------------------------------------------------------------
@@ -499,10 +505,10 @@ last_delay_timer({{_,_},_}, TRef, {LastServer, _}) ->
last_delay_timer({_,_}, TRef, {_, LastClient}) ->
{TRef, LastClient}.
-%% If we can not generate a not allready in use session ID in
+%% If we cannot generate a not allready in use session ID in
%% ?GEN_UNIQUE_ID_MAX_TRIES we make the new session uncacheable The
%% value of ?GEN_UNIQUE_ID_MAX_TRIES is stolen from open SSL which
-%% states : "If we can not find a session id in
+%% states : "If we cannot find a session id in
%% ?GEN_UNIQUE_ID_MAX_TRIES either the RAND code is broken or someone
%% is trying to open roughly very close to 2^128 (or 2^256) SSL
%% sessions to our server"
@@ -513,7 +519,7 @@ new_id(Port, Tries, Cache, CacheCb) ->
case CacheCb:lookup(Cache, {Port, Id}) of
undefined ->
Now = erlang:monotonic_time(),
- %% New sessions can not be set to resumable
+ %% New sessions cannot be set to resumable
%% until handshake is compleate and the
%% other session values are set.
CacheCb:update(Cache, {Port, Id}, #session{session_id = Id,
diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl
index 115ab4451d..a952e20133 100644
--- a/lib/ssl/src/ssl_pem_cache.erl
+++ b/lib/ssl/src/ssl_pem_cache.erl
@@ -29,7 +29,7 @@
-export([start_link/1,
start_link_dist/1,
name/1,
- insert/1,
+ insert/2,
clear/0]).
% Spawn export
@@ -90,19 +90,17 @@ start_link_dist(_) ->
%%--------------------------------------------------------------------
--spec insert(binary()) -> {ok, term()} | {error, reason()}.
+-spec insert(binary(), term()) -> ok | {error, reason()}.
%%
%% Description: Cache a pem file and return its content.
%%--------------------------------------------------------------------
-insert(File) ->
- {ok, PemBin} = file:read_file(File),
- Content = public_key:pem_decode(PemBin),
+insert(File, Content) ->
case bypass_cache() of
true ->
- {ok, Content};
+ ok;
false ->
cast({cache_pem, File, Content}),
- {ok, Content}
+ ok
end.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl
index 8828c3a0d8..e7e4af942a 100644
--- a/lib/ssl/src/ssl_pkix_db.erl
+++ b/lib/ssl/src/ssl_pkix_db.erl
@@ -27,6 +27,7 @@
-include("ssl_internal.hrl").
-include_lib("public_key/include/public_key.hrl").
-include_lib("kernel/include/file.hrl").
+-include_lib("kernel/include/logger.hrl").
-export([create/1, create_pem_cache/1,
add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3,
@@ -157,7 +158,7 @@ extract_trusted_certs(File) ->
{error, {badmatch, Error}}
end.
--spec decode_pem_file(binary()) -> {ok, term()}.
+-spec decode_pem_file(binary()) -> {ok, term()} | {error, term()}.
decode_pem_file(File) ->
case file:read_file(File) of
{ok, PemBin} ->
@@ -311,16 +312,21 @@ decode_certs(Ref, Cert) ->
error:_ ->
Report = io_lib:format("SSL WARNING: Ignoring a CA cert as "
"it could not be correctly decoded.~n", []),
- error_logger:info_report(Report),
+ ?LOG_NOTICE(Report),
undefined
end.
new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->
- Ref = make_ref(),
- init_ref_db(Ref, File, RefsDb),
- {ok, Content} = ssl_pem_cache:insert(File),
- add_certs_from_pem(Content, Ref, CertsDb),
- {ok, Ref}.
+ case decode_pem_file(File) of
+ {ok, Content} ->
+ Ref = make_ref(),
+ init_ref_db(Ref, File, RefsDb),
+ ok = ssl_pem_cache:insert(File, Content),
+ add_certs_from_pem(Content, Ref, CertsDb),
+ {ok, Ref};
+ Error ->
+ Error
+ end.
add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) ->
[add_crls(CRL, Mapping) || CRL <- CRLs];
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index ed007f58d7..e8ce50040f 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -74,7 +74,7 @@
-define(INITIAL_BYTES, 5).
-define(MAX_SEQENCE_NUMBER, 18446744073709551615). %% (1 bsl 64) - 1 = 18446744073709551615
-%% Sequence numbers can not wrap so when max is about to be reached we should renegotiate.
+%% Sequence numbers cannot wrap so when max is about to be reached we should renegotiate.
%% We will renegotiate a little before so that there will be sequence numbers left
%% for the rehandshake and a little data. Currently we decided to renegotiate a little more
%% often as we can have a cheaper test to check if it is time to renegotiate. It will still
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index a3002830d1..8320d3f7f3 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -38,7 +38,8 @@
-include("ssl_api.hrl").
-include("ssl_internal.hrl").
-include("ssl_srp.hrl").
--include_lib("public_key/include/public_key.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Internal application API
@@ -111,12 +112,13 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
gen_statem:enter_loop(?MODULE, [], init, State)
catch throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error, State0})
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
end.
%%====================================================================
%% State transition handling
@@ -129,6 +131,7 @@ next_record(#state{protocol_buffers =
= Buffers,
connection_states = ConnStates0,
ssl_options = #ssl_options{padding_check = Check}} = State) ->
+
case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
{Plain, ConnStates} ->
{Plain, State#state{protocol_buffers =
@@ -264,9 +267,19 @@ send_handshake(Handshake, State) ->
queue_handshake(Handshake, #state{negotiated_version = Version,
tls_handshake_history = Hist0,
flight_buffer = Flight0,
- connection_states = ConnectionStates0} = State0) ->
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = State0) ->
{BinHandshake, ConnectionStates, Hist} =
encode_handshake(Handshake, Version, ConnectionStates0, Hist0),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinHandshake},
+ HandshakeMsg = #{direction => outbound,
+ protocol => 'handshake',
+ message => Handshake},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, HandshakeMsg, #{domain => [otp,ssl,handshake]}),
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
+
State0#state{connection_states = ConnectionStates,
tls_handshake_history = Hist,
flight_buffer = Flight0 ++ [BinHandshake]}.
@@ -278,10 +291,15 @@ send_handshake_flight(#state{socket = Socket,
{State0#state{flight_buffer = []}, []}.
queue_change_cipher(Msg, #state{negotiated_version = Version,
- flight_buffer = Flight0,
- connection_states = ConnectionStates0} = State0) ->
+ flight_buffer = Flight0,
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = State0) ->
{BinChangeCipher, ConnectionStates} =
encode_change_cipher(Msg, Version, ConnectionStates0),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinChangeCipher},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
State0#state{connection_states = ConnectionStates,
flight_buffer = Flight0 ++ [BinChangeCipher]}.
@@ -309,10 +327,16 @@ empty_connection_state(ConnectionEnd, BeastMitigation) ->
send_alert(Alert, #state{negotiated_version = Version,
socket = Socket,
transport_cb = Transport,
- connection_states = ConnectionStates0} = State0) ->
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = State0) ->
{BinMsg, ConnectionStates} =
encode_alert(Alert, Version, ConnectionStates0),
+
send(Transport, Socket, BinMsg),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinMsg},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
State0#state{connection_states = ConnectionStates}.
%%--------------------------------------------------------------------
@@ -415,6 +439,14 @@ init({call, From}, {start, Timeout},
{BinMsg, ConnectionStates, Handshake} =
encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
send(Transport, Socket, BinMsg),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinMsg},
+ HelloMsg = #{direction => outbound,
+ protocol => 'handshake',
+ message => Hello},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, HelloMsg, #{domain => [otp,ssl,handshake]}),
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
State1 = State0#state{connection_states = ConnectionStates,
negotiated_version = Version, %% Requested version
session =
@@ -432,17 +464,12 @@ init(Type, Event, State) ->
{start, timeout()} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-
-error({call, From}, {start, _Timeout}, {Error, State}) ->
- ssl_connection:stop_and_reply(
- normal, {reply, From, {error, Error}}, State);
error({call, From}, {start, _Timeout},
#state{protocol_specific = #{error := Error}} = State) ->
ssl_connection:stop_and_reply(
normal, {reply, From, {error, Error}}, State);
-error({call, _} = Call, Msg, {Error, #state{protocol_specific = Map} = State}) ->
- gen_handshake(?FUNCTION_NAME, Call, Msg,
- State#state{protocol_specific = Map#{error => Error}});
+error({call, _} = Call, Msg, State) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg, State);
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
@@ -651,11 +678,11 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
next_tls_record(Data, StateName, #state{protocol_buffers =
#protocol_buffers{tls_record_buffer = Buf0,
- tls_cipher_texts = CT0} = Buffers}
- = State0) ->
- case tls_record:get_tls_records(Data,
+ tls_cipher_texts = CT0} = Buffers,
+ ssl_options = SslOpts} = State0) ->
+ case tls_record:get_tls_records(Data,
acceptable_record_versions(StateName, State0),
- Buf0) of
+ Buf0, SslOpts) of
{Records, Buf1} ->
CT1 = CT0 ++ Records,
next_record(State0#state{protocol_buffers =
@@ -666,10 +693,18 @@ next_tls_record(Data, StateName, #state{protocol_buffers =
end.
+%% TLS 1.3 Client/Server
+%% - Ignore TLSPlaintext.legacy_record_version
+%% - Verify that TLSCiphertext.legacy_record_version is set to 0x0303 for all records
+%% other than an initial ClientHello, where it MAY also be 0x0301.
acceptable_record_versions(hello, _) ->
- [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_AVAILABLE_VERSIONS];
+ [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_TLS_RECORD_VERSIONS];
+acceptable_record_versions(_, #state{negotiated_version = {Major, Minor}})
+ when Major > 3; Major =:= 3, Minor >= 4 ->
+ [{3, 3}];
acceptable_record_versions(_, #state{negotiated_version = Version}) ->
[Version].
+
handle_record_alert(Alert, _) ->
Alert.
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index f1eecb2875..2ad1386900 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -31,6 +31,7 @@
-include("ssl_internal.hrl").
-include("ssl_cipher.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Handshake handling
-export([client_hello/8, hello/4]).
@@ -60,6 +61,18 @@ client_hello(Host, Port, ConnectionStates,
} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = tls_record:highest_protocol_version(Versions),
+
+ %% In TLS 1.3, the client indicates its version preferences in the
+ %% "supported_versions" extension (Section 4.2.1) and the
+ %% legacy_version field MUST be set to 0x0303, which is the version
+ %% number for TLS 1.2.
+ LegacyVersion =
+ case tls_record:is_higher(Version, {3,2}) of
+ true ->
+ {3,3};
+ false ->
+ Version
+ end,
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates, read),
AvailableCipherSuites = ssl_handshake:available_suites(UserSuites, Version),
@@ -70,7 +83,7 @@ client_hello(Host, Port, ConnectionStates,
CipherSuites = ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation, Fallback),
Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
#client_hello{session_id = Id,
- client_version = Version,
+ client_version = LegacyVersion,
cipher_suites = CipherSuites,
compression_methods = ssl_record:compressions(),
random = SecParams#security_parameters.client_random,
@@ -92,6 +105,65 @@ client_hello(Host, Port, ConnectionStates,
%%
%% Description: Handles a received hello message
%%--------------------------------------------------------------------
+
+
+%% TLS 1.3 - Section 4.1.3
+%% TLS 1.3 clients receiving a ServerHello indicating TLS 1.2 or below
+%% MUST check that the last eight bytes are not equal to either of these
+%% values.
+hello(#server_hello{server_version = {Major, Minor},
+ random = <<_:24/binary,Down:8/binary>>},
+ #ssl_options{versions = [{M,N}|_]}, _, _)
+ when (M > 3 orelse M =:= 3 andalso N >= 4) andalso %% TLS 1.3 client
+ (Major =:= 3 andalso Minor =:= 3 andalso %% Negotiating TLS 1.2
+ Down =:= ?RANDOM_OVERRIDE_TLS12) orelse
+
+ (M > 3 orelse M =:= 3 andalso N >= 4) andalso %% TLS 1.3 client
+ (Major =:= 3 andalso Minor < 3 andalso %% Negotiating TLS 1.1 or prior
+ Down =:= ?RANDOM_OVERRIDE_TLS11) ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+
+%% TLS 1.2 clients SHOULD also check that the last eight bytes are not
+%% equal to the second value if the ServerHello indicates TLS 1.1 or below.
+hello(#server_hello{server_version = {Major, Minor},
+ random = <<_:24/binary,Down:8/binary>>},
+ #ssl_options{versions = [{M,N}|_]}, _, _)
+ when (M =:= 3 andalso N =:= 3) andalso %% TLS 1.2 client
+ (Major =:= 3 andalso Minor < 3 andalso %% Negotiating TLS 1.1 or prior
+ Down =:= ?RANDOM_OVERRIDE_TLS11) ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+
+
+%% TLS 1.3 - 4.2.1. Supported Versions
+%% If the "supported_versions" extension in the ServerHello contains a
+%% version not offered by the client or contains a version prior to TLS
+%% 1.3, the client MUST abort the handshake with an "illegal_parameter"
+%% alert.
+%%--------------------------------------------------------------------
+%% TLS 1.2 Client
+%%
+%% - If "supported_version" is present (ServerHello):
+%% - Abort handshake with an "illegal_parameter" alert
+hello(#server_hello{server_version = Version,
+ extensions = #hello_extensions{
+ server_hello_selected_version =
+ #server_hello_selected_version{selected_version = Version}
+ }},
+ #ssl_options{versions = SupportedVersions},
+ _ConnectionStates0, _Renegotiation) ->
+ case tls_record:is_higher({3,4}, Version) of
+ true ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ false ->
+ case tls_record:is_acceptable_version(Version, SupportedVersions) of
+ true ->
+ %% Implement TLS 1.3 statem ???
+ ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION);
+ false ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)
+ end
+ end;
+
hello(#server_hello{server_version = Version, random = Random,
cipher_suite = CipherSuite,
compression_method = Compression,
@@ -106,6 +178,37 @@ hello(#server_hello{server_version = Version, random = Random,
false ->
?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
end;
+
+
+%% TLS 1.2 Server
+%% - If "supported_versions" is present (ClientHello):
+%% - Select version from "supported_versions" (ignore ClientHello.legacy_version)
+%% - If server only supports versions greater than "supported_versions":
+%% - Abort handshake with a "protocol_version" alert (*)
+%% - If "supported_versions" is absent (ClientHello):
+%% - Negotiate the minimum of ClientHello.legacy_version and TLS 1.2 (**)
+%% - If server only supports versions greater than ClientHello.legacy_version:
+%% - Abort handshake with a "protocol_version" alert
+%%
+%% (*) Sends alert even if there is a gap in supported versions
+%% e.g. Server 1.0,1.2 Client 1.1,1.3
+%% (**) Current implementation can negotiate a version not supported by the client
+%% e.g. Server 1.0,1.2 Client 1.1 -> ServerHello 1.0
+hello(#client_hello{client_version = _ClientVersion,
+ cipher_suites = CipherSuites,
+ extensions = #hello_extensions{
+ client_hello_versions =
+ #client_hello_versions{versions = ClientVersions}
+ }} = Hello,
+ #ssl_options{versions = Versions} = SslOpts,
+ Info, Renegotiation) ->
+ try
+ Version = ssl_handshake:select_supported_version(ClientVersions, Versions),
+ do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation)
+ catch
+ _:_ ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
+ end;
hello(#client_hello{client_version = ClientVersion,
cipher_suites = CipherSuites} = Hello,
@@ -113,19 +216,11 @@ hello(#client_hello{client_version = ClientVersion,
Info, Renegotiation) ->
try
Version = ssl_handshake:select_version(tls_record, ClientVersion, Versions),
- case ssl_cipher:is_fallback(CipherSuites) of
- true ->
- Highest = tls_record:highest_protocol_version(Versions),
- case tls_record:is_higher(Highest, Version) of
- true ->
- ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
- false ->
- handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
- end;
- false ->
- handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
- end
+ do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation)
catch
+ error:{case_clause,{asn1, Asn1Reason}} ->
+ %% ASN-1 decode of certificate somehow failed
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason});
_:_ ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
end.
@@ -241,6 +336,31 @@ handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
{ConnectionStates, ProtoExt, Protocol} ->
{Version, SessionId, ConnectionStates, ProtoExt, Protocol}
end.
+
+
+do_hello(undefined, _Versions, _CipherSuites, _Hello, _SslOpts, _Info, _Renegotiation) ->
+ ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION);
+do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation) ->
+ case tls_record:is_higher({3,4}, Version) of
+ true -> %% TLS 1.2 and older
+ case ssl_cipher:is_fallback(CipherSuites) of
+ true ->
+ Highest = tls_record:highest_protocol_version(Versions),
+ case tls_record:is_higher(Highest, Version) of
+ true ->
+ ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
+ false ->
+ handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
+ end;
+ false ->
+ handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
+ end;
+ false ->
+ %% Implement TLS 1.3 statem ???
+ ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ end.
+
+
%%--------------------------------------------------------------------
enc_handshake(#hello_request{}, _Version) ->
{?HELLO_REQUEST, <<>>};
@@ -272,6 +392,10 @@ get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
try decode_handshake(Version, Type, Body) of
Handshake ->
+ Report = #{direction => inbound,
+ protocol => 'handshake',
+ message => Handshake},
+ ssl_logger:debug(Opts#ssl_options.log_level, Report, #{domain => [otp,ssl,handshake]}),
get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
catch
_:_ ->
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index f1aca8c801..444759aafa 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -30,9 +30,10 @@
-include("ssl_alert.hrl").
-include("tls_handshake.hrl").
-include("ssl_cipher.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Handling of incoming data
--export([get_tls_records/3, init_connection_states/2]).
+-export([get_tls_records/4, init_connection_states/2]).
%% Encoding TLS records
-export([encode_handshake/3, encode_alert_record/3,
@@ -75,24 +76,24 @@ init_connection_states(Role, BeastMitigation) ->
pending_write => Pending}.
%%--------------------------------------------------------------------
--spec get_tls_records(binary(), [tls_version()], binary()) -> {[binary()], binary()} | #alert{}.
+-spec get_tls_records(binary(), [tls_version()], binary(), ssl_options()) -> {[binary()], binary()} | #alert{}.
%%
%% and returns it as a list of tls_compressed binaries also returns leftover
%% Description: Given old buffer and new data from TCP, packs up a records
%% data
%%--------------------------------------------------------------------
-get_tls_records(Data, Versions, Buffer) ->
+get_tls_records(Data, Versions, Buffer, SslOpts) ->
BinData = list_to_binary([Buffer, Data]),
case erlang:byte_size(BinData) of
N when N >= 3 ->
case assert_version(BinData, Versions) of
true ->
- get_tls_records_aux(BinData, []);
+ get_tls_records_aux(BinData, [], SslOpts);
false ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end;
_ ->
- get_tls_records_aux(BinData, [])
+ get_tls_records_aux(BinData, [], SslOpts)
end.
%%====================================================================
@@ -229,6 +230,8 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
%% Description: Creates a protocol version record from a version atom
%% or vice versa.
%%--------------------------------------------------------------------
+protocol_version('tlsv1.3') ->
+ {3, 4};
protocol_version('tlsv1.2') ->
{3, 3};
protocol_version('tlsv1.1') ->
@@ -239,6 +242,8 @@ protocol_version(sslv3) ->
{3, 0};
protocol_version(sslv2) -> %% Backwards compatibility
{2, 0};
+protocol_version({3, 4}) ->
+ 'tlsv1.3';
protocol_version({3, 3}) ->
'tlsv1.2';
protocol_version({3, 2}) ->
@@ -399,33 +404,61 @@ assert_version(<<?BYTE(_), ?BYTE(MajVer), ?BYTE(MinVer), _/binary>>, Versions) -
get_tls_records_aux(<<?BYTE(?APPLICATION_DATA),?BYTE(MajVer),?BYTE(MinVer),
?UINT16(Length), Data:Length/binary, Rest/binary>>,
- Acc) ->
+ Acc, SslOpts) ->
+ RawTLSRecord = <<?BYTE(?APPLICATION_DATA),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Length), Data:Length/binary>>,
+ Report = #{direction => inbound,
+ protocol => 'tls_record',
+ message => [RawTLSRecord]},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
get_tls_records_aux(Rest, [#ssl_tls{type = ?APPLICATION_DATA,
version = {MajVer, MinVer},
- fragment = Data} | Acc]);
+ fragment = Data} | Acc],
+ SslOpts);
get_tls_records_aux(<<?BYTE(?HANDSHAKE),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Length),
- Data:Length/binary, Rest/binary>>, Acc) ->
+ ?UINT16(Length),
+ Data:Length/binary, Rest/binary>>, Acc, SslOpts) ->
+ RawTLSRecord = <<?BYTE(?HANDSHAKE),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Length), Data:Length/binary>>,
+ Report = #{direction => inbound,
+ protocol => 'tls_record',
+ message => [RawTLSRecord]},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
get_tls_records_aux(Rest, [#ssl_tls{type = ?HANDSHAKE,
version = {MajVer, MinVer},
- fragment = Data} | Acc]);
+ fragment = Data} | Acc],
+ SslOpts);
get_tls_records_aux(<<?BYTE(?ALERT),?BYTE(MajVer),?BYTE(MinVer),
?UINT16(Length), Data:Length/binary,
- Rest/binary>>, Acc) ->
+ Rest/binary>>, Acc, SslOpts) ->
+ RawTLSRecord = <<?BYTE(?ALERT),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Length), Data:Length/binary>>,
+ Report = #{direction => inbound,
+ protocol => 'tls_record',
+ message => [RawTLSRecord]},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
get_tls_records_aux(Rest, [#ssl_tls{type = ?ALERT,
version = {MajVer, MinVer},
- fragment = Data} | Acc]);
+ fragment = Data} | Acc],
+ SslOpts);
get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
?UINT16(Length), Data:Length/binary, Rest/binary>>,
- Acc) ->
+ Acc, SslOpts) ->
+ RawTLSRecord = <<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Length), Data:Length/binary>>,
+ Report = #{direction => inbound,
+ protocol => 'tls_record',
+ message => [RawTLSRecord]},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
version = {MajVer, MinVer},
- fragment = Data} | Acc]);
+ fragment = Data} | Acc],
+ SslOpts);
get_tls_records_aux(<<0:1, _CT:7, ?BYTE(_MajVer), ?BYTE(_MinVer),
?UINT16(Length), _/binary>>,
- _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
+ _Acc, _SslOpts) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-get_tls_records_aux(Data, Acc) ->
+get_tls_records_aux(Data, Acc, _SslOpts) ->
case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
true ->
{lists:reverse(Acc), Data};
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index d6b500748e..6ef6040761 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -74,7 +74,7 @@ finished(Role, Version, PrfAlgo, MasterSecret, Handshake)
prf(?MD5SHA, MasterSecret, finished_label(Role), [MD5, SHA], 12);
finished(Role, Version, PrfAlgo, MasterSecret, Handshake)
- when Version == 3 ->
+ when Version == 3; Version == 4 ->
%% RFC 5246 - 7.4.9. Finished
%% struct {
%% opaque verify_data[12];
@@ -85,6 +85,7 @@ finished(Role, Version, PrfAlgo, MasterSecret, Handshake)
Hash = crypto:hash(mac_algo(PrfAlgo), Handshake),
prf(PrfAlgo, MasterSecret, finished_label(Role), Hash, 12).
+
-spec certificate_verify(md5sha | sha, integer(), [binary()]) -> binary().
certificate_verify(md5sha, _Version, Handshake) ->
@@ -154,7 +155,7 @@ setup_keys(Version, _PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize
%% TLS v1.2
setup_keys(Version, PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
KeyMatLen, IVSize)
- when Version == 3 ->
+ when Version == 3; Version == 4 ->
%% RFC 5246 - 6.3. Key calculation
%% key_block = PRF(SecurityParameters.master_secret,
%% "key expansion",
@@ -192,7 +193,7 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
Fragment]),
Mac.
--spec suites(1|2|3) -> [ssl_cipher:cipher_suite()].
+-spec suites(1|2|3|4) -> [ssl_cipher:cipher_suite()].
suites(Minor) when Minor == 1; Minor == 2 ->
[
@@ -244,8 +245,15 @@ suites(3) ->
%% ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
%% ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
%% ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256
- ] ++ suites(2).
+ ] ++ suites(2);
+
+
+suites(4) ->
+ suites(3).
+
+signature_algs({3, 4}, HashSigns) ->
+ signature_algs({3, 3}, HashSigns);
signature_algs({3, 3}, HashSigns) ->
CryptoSupports = crypto:supports(),
Hashes = proplists:get_value(hashs, CryptoSupports),
@@ -273,6 +281,8 @@ signature_algs({3, 3}, HashSigns) ->
end, [], HashSigns),
lists:reverse(Supported).
+default_signature_algs({3, 4}) ->
+ default_signature_algs({3, 3});
default_signature_algs({3, 3} = Version) ->
Default = [%% SHA2
{sha512, ecdsa},
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index 3c8eda1812..c93f066825 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -43,10 +43,10 @@ all() ->
groups() ->
[
- {'tlsv1.2', [], test_cases()},
+ {'tlsv1.2', [], [mix_sign | test_cases()]},
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()},
- {'dtlsv1.2', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
{'dtlsv1', [], test_cases()}
].
@@ -288,22 +288,22 @@ client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdh_rsa, ecdhe_rsa, Config),
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_rsa, ecdhe_ecdsa, Config),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
@@ -315,29 +315,30 @@ client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_rsa, ecdhe_rsa, Config),
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
- {client_chain, Default}],
- ecdhe_rsa, ecdh_rsa, Config),
+ {client_chain, Default}],
+ ecdhe_rsa, ecdh_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
-
+ Expected = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(0))), %% The certificate curve
+
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(Expected, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
@@ -345,7 +346,7 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
@@ -357,13 +358,13 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_ecdsa, ecdhe_rsa, Config),
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_rsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
- true -> ssl_test_lib:ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
@@ -371,7 +372,7 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, sect571r1]}],
@@ -383,8 +384,8 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
- ecdhe_rsa, ecdhe_ecdsa, Config),
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, sect571r1]}],
@@ -392,3 +393,12 @@ client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
false -> {skip, "unsupported named curves"}
end.
+
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
index 5a08b152a6..81a7dfd2da 100644
--- a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
@@ -57,13 +57,13 @@ all_groups() ->
groups() ->
case ssl_test_lib:openssl_sane_dtls() of
true ->
- [{'tlsv1.2', [], test_cases()},
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()},
- {'dtlsv1.2', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
{'dtlsv1', [], test_cases()}];
false ->
- [{'tlsv1.2', [], test_cases()},
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()}]
end.
@@ -202,6 +202,17 @@ client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
+
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], [{client_type, erlang},
+ {server_type, openssl} | Config]).
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 959de60f57..480988b6e4 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -147,8 +147,7 @@ options_tests_tls() ->
tls_tcp_reuseaddr].
api_tests() ->
- [connection_info,
- secret_connection_info,
+ [secret_connection_info,
connection_information,
peercert,
peercert_with_client_cert,
@@ -243,7 +242,9 @@ error_handling_tests()->
[close_transport_accept,
recv_active,
recv_active_once,
- recv_error_handling
+ recv_error_handling,
+ call_in_error_state,
+ close_in_error_state
].
error_handling_tests_tls()->
@@ -476,6 +477,8 @@ init_per_testcase(TestCase, Config) when TestCase == tls_ssl_accept_timeout;
TestCase == tls_client_closes_socket;
TestCase == tls_closed_in_active_once;
TestCase == tls_downgrade ->
+ ssl:stop(),
+ ssl:start(),
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 15}),
Config;
@@ -610,7 +613,16 @@ new_options_in_accept(Config) when is_list(Config) ->
[_ , _ | ServerSslOpts] = ssl_test_lib:ssl_options(server_opts, Config), %% Remove non ssl opts
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Version = ssl_test_lib:protocol_options(Config, [{tls, sslv3}, {dtls, dtlsv1}]),
- Cipher = ssl_test_lib:protocol_options(Config, [{tls, {rsa,rc4_128,sha}}, {dtls, {rsa,aes_128_cbc,sha}}]),
+ Cipher = ssl_test_lib:protocol_options(Config, [{tls, #{key_exchange =>rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf
+ }},
+ {dtls, #{key_exchange =>rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf
+ }}]),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{ssl_extra_opts, [{versions, [Version]},
@@ -739,41 +751,6 @@ prf(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-connection_info() ->
- [{doc,"Test the API function ssl:connection_information/2"}].
-connection_info(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options, ServerOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options,
- [{ciphers,[{dhe_rsa, aes_128_cbc, sha}]} |
- ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- Version = ssl_test_lib:protocol_version(Config),
-
- ServerMsg = ClientMsg = {ok, {Version, {dhe_rsa, aes_128_cbc, sha}}},
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
secret_connection_info() ->
[{doc,"Test the API function ssl:connection_information/2"}].
secret_connection_info(Config) when is_list(Config) ->
@@ -3475,16 +3452,50 @@ tls_tcp_reuseaddr(Config) when is_list(Config) ->
honor_server_cipher_order() ->
[{doc,"Test API honor server cipher order."}].
honor_server_cipher_order(Config) when is_list(Config) ->
- ClientCiphers = [{dhe_rsa, aes_128_cbc, sha}, {dhe_rsa, aes_256_cbc, sha}],
- ServerCiphers = [{dhe_rsa, aes_256_cbc, sha}, {dhe_rsa, aes_128_cbc, sha}],
-honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, {dhe_rsa, aes_256_cbc, sha}).
+ ClientCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}],
+ ServerCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac =>sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}],
+ honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}).
honor_client_cipher_order() ->
[{doc,"Test API honor server cipher order."}].
honor_client_cipher_order(Config) when is_list(Config) ->
- ClientCiphers = [{dhe_rsa, aes_128_cbc, sha}, {dhe_rsa, aes_256_cbc, sha}],
- ServerCiphers = [{dhe_rsa, aes_256_cbc, sha}, {dhe_rsa, aes_128_cbc, sha}],
-honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, {dhe_rsa, aes_128_cbc, sha}).
+ ClientCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}],
+ ServerCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac =>sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}],
+honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}).
honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
@@ -3516,7 +3527,7 @@ honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) ->
%%--------------------------------------------------------------------
tls_ciphersuite_vs_version() ->
- [{doc,"Test a SSLv3 client can not negotiate a TLSv* cipher suite."}].
+ [{doc,"Test a SSLv3 client cannot negotiate a TLSv* cipher suite."}].
tls_ciphersuite_vs_version(Config) when is_list(Config) ->
{_ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -3993,6 +4004,64 @@ recv_error_handling(Config) when is_list(Config) ->
ssl:close(SslSocket),
ssl_test_lib:check_result(Server, ok).
+
+
+%%--------------------------------------------------------------------
+call_in_error_state() ->
+ [{doc,"Special case of call error handling"}].
+call_in_error_state(Config) when is_list(Config) ->
+ ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)],
+ Pid = spawn_link(?MODULE, run_error_server, [[self() | ServerOpts]]),
+ receive
+ {Pid, Port} ->
+ spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]])
+ end,
+ receive
+ {error, closed} ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+
+run_client_error([Port, Opts]) ->
+ ssl:connect("localhost", Port, Opts).
+
+run_error_server([ Pid | Opts]) ->
+ {ok, Listen} = ssl:listen(0, Opts),
+ {ok,{_, Port}} = ssl:sockname(Listen),
+ Pid ! {self(), Port},
+ {ok, Socket} = ssl:transport_accept(Listen),
+ Pid ! ssl:controlling_process(Socket, self()).
+
+%%--------------------------------------------------------------------
+
+close_in_error_state() ->
+ [{doc,"Special case of closing socket in error state"}].
+close_in_error_state(Config) when is_list(Config) ->
+ ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)],
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ _ = spawn_link(?MODULE, run_error_server_close, [[self() | ServerOpts]]),
+ receive
+ {_Pid, Port} ->
+ spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]])
+ end,
+ receive
+ ok ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+
+run_error_server_close([Pid | Opts]) ->
+ {ok, Listen} = ssl:listen(0, Opts),
+ {ok,{_, Port}} = ssl:sockname(Listen),
+ Pid ! {self(), Port},
+ {ok, Socket} = ssl:transport_accept(Listen),
+ Pid ! ssl:close(Socket).
+
%%--------------------------------------------------------------------
rizzo() ->
@@ -4212,17 +4281,17 @@ unordered_protocol_versions_server(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ClientOpts}]),
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+
+ ServerMsg = ClientMsg = {ok,'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -4237,18 +4306,17 @@ unordered_protocol_versions_client(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ServerOpts }]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
-
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+
+ ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -4964,6 +5032,7 @@ run_suites(Ciphers, Config, Type) ->
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]}
end,
+ ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, ssl_test_lib:filter_suites(Ciphers, Version)]),
Result = lists:map(fun(Cipher) ->
cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
ssl_test_lib:filter_suites(Ciphers, Version)),
@@ -4976,7 +5045,7 @@ run_suites(Ciphers, Config, Type) ->
end.
erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher:erl_suite_definition(ssl_cipher:openssl_suite(Suite));
+ ssl_cipher:suite_definition(ssl_cipher:openssl_suite(Suite));
erlang_cipher_suite(Suite) ->
Suite.
@@ -5028,8 +5097,13 @@ connection_information_result(Socket) ->
end.
connection_info_result(Socket) ->
- {ok, Info} = ssl:connection_information(Socket, [protocol, cipher_suite]),
- {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}}.
+ {ok, Info} = ssl:connection_information(Socket, [protocol, selected_cipher_suite]),
+ {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}}.
+
+protocol_info_result(Socket) ->
+ {ok, [{protocol, PVersion}]} = ssl:connection_information(Socket, [protocol]),
+ {ok, PVersion}.
+
version_info_result(Socket) ->
{ok, [{version, Version}]} = ssl:connection_information(Socket, [version]),
{ok, Version}.
@@ -5158,20 +5232,6 @@ try_recv_active_once(Socket) ->
{error, einval} = ssl:recv(Socket, 11),
ok.
-first_rsa_suite([{ecdhe_rsa, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{ecdhe_rsa, _, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([_ | Rest]) ->
- first_rsa_suite(Rest).
wait_for_send(Socket) ->
%% Make sure TLS process processed send message event
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 63e9d07d0b..c0981a9eaf 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -513,7 +513,7 @@ verify_fun_always_run_client(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
%% If user verify fun is called correctly we fail the connection.
- %% otherwise we can not tell this case apart form where we miss
+ %% otherwise we cannot tell this case apart form where we miss
%% to call users verify fun
FunAndState = {fun(_,{extension, _}, UserState) ->
{unknown, UserState};
@@ -552,7 +552,7 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
%% If user verify fun is called correctly we fail the connection.
- %% otherwise we can not tell this case apart form where we miss
+ %% otherwise we cannot tell this case apart form where we miss
%% to call users verify fun
FunAndState = {fun(_,{extension, _}, UserState) ->
{unknown, UserState};
diff --git a/lib/ssl/test/ssl_engine_SUITE.erl b/lib/ssl/test/ssl_engine_SUITE.erl
index 7277dad012..1423c99dc2 100644
--- a/lib/ssl/test/ssl_engine_SUITE.erl
+++ b/lib/ssl/test/ssl_engine_SUITE.erl
@@ -117,8 +117,23 @@ private_key(Config) when is_list(Config) ->
EngineServerConf = [{key, #{algorithm => rsa,
engine => Engine,
key_id => ServerKey}} | proplists:delete(key, ServerConf)],
+
+ EngineFileClientConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ClientKey}} |
+ proplists:delete(keyfile, FileClientConf)],
+
+ EngineFileServerConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ServerKey}} |
+ proplists:delete(keyfile, FileServerConf)],
+
%% Test with engine
test_tls_connection(EngineServerConf, EngineClientConf, Config),
+
+ %% Test with engine and present file arugments
+ test_tls_connection(EngineFileServerConf, EngineFileClientConf, Config),
+
%% Test that sofware fallback is available
test_tls_connection(ServerConf, [{reuse_sessions, false} |ClientConf], Config).
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 2c7c62407e..9ae04184e2 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -149,7 +149,7 @@ decode_single_hello_sni_extension_correctly(_Config) ->
Exts = Decoded.
decode_empty_server_sni_correctly(_Config) ->
- Exts = #hello_extensions{sni = ""},
+ Exts = #hello_extensions{sni = #sni{hostname = ""}},
SNI = <<?UINT16(?SNI_EXT),?UINT16(0)>>,
Decoded = ssl_handshake:decode_hello_extensions(SNI),
Exts = Decoded.
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index 96b15d9b51..3b79780974 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -34,7 +34,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [pem_cleanup].
+ [pem_cleanup, invalid_insert].
groups() ->
[].
@@ -68,6 +68,10 @@ init_per_testcase(pem_cleanup = Case, Config) ->
application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL),
ssl:start(),
ct:timetrap({minutes, 1}),
+ Config;
+init_per_testcase(_, Config) ->
+ ssl:start(),
+ ct:timetrap({seconds, 5}),
Config.
end_per_testcase(_TestCase, Config) ->
@@ -108,7 +112,34 @@ pem_cleanup(Config)when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client),
false = Size == Size1.
-
+
+invalid_insert() ->
+ [{doc, "Test that insert of invalid pem does not cause empty cache entry"}].
+invalid_insert(Config)when is_list(Config) ->
+ process_flag(trap_exit, true),
+
+ ClientOpts = proplists:get_value(client_verification_opts, Config),
+ ServerOpts = proplists:get_value(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} | proplists:delete(cacertfile, ClientOpts)],
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()}, {options, BadClientOpts}]),
+ ssl_test_lib:close(Server),
+ 1 = ssl_pkix_db:db_size(get_fileref_db()).
+
+
+
+%%--------------------------------------------------------------------
+%% Internal funcations
+%%--------------------------------------------------------------------
+
get_pem_cache() ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
@@ -120,6 +151,16 @@ get_pem_cache() ->
undefined
end.
+get_fileref_db() ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ case element(6, State) of
+ [_CertDb, {FileRefDb,_} | _] ->
+ FileRefDb;
+ _ ->
+ undefined
+ end.
later()->
DateTime = calendar:now_to_local_time(os:timestamp()),
Gregorian = calendar:datetime_to_gregorian_seconds(DateTime),
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 39acc65f6c..7202e3662c 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -585,6 +585,17 @@ default_cert_chain_conf() ->
%% Use only default options
[[],[],[]].
+gen_conf(mix, mix, UserClient, UserServer) ->
+ ClientTag = conf_tag("client"),
+ ServerTag = conf_tag("server"),
+
+ DefaultClient = default_cert_chain_conf(),
+ DefaultServer = default_cert_chain_conf(),
+
+ ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
+ ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
+
+ new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]);
gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) ->
ClientTag = conf_tag("client"),
ServerTag = conf_tag("server"),
@@ -678,6 +689,32 @@ merge_spec(User, Default, [Conf | Rest], Acc) ->
merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
end.
+make_mix_cert(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]),
+ ClientChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, {namedCurve, CurveOid}}, {extensions, Ext}]
+ ],
+ ServerChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, {namedCurve, CurveOid}},{extensions, Ext}]
+ ],
+ ClientChainType =ServerChainType = mix,
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
make_ecdsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of
@@ -1097,8 +1134,6 @@ check_ecc(SSL, Role, Expect) ->
{ok, Data} = ssl:connection_information(SSL),
case lists:keyfind(ecc, 1, Data) of
{ecc, {named_curve, Expect}} -> ok;
- false when Expect == undefined -> ok;
- false when Expect == secp256r1 andalso Role == client_no_ecc -> ok;
Other -> {error, Role, Expect, Other}
end.
@@ -1186,13 +1221,13 @@ common_ciphers(crypto) ->
common_ciphers(openssl) ->
OpenSslSuites =
string:tokens(string:strip(os:cmd("openssl ciphers"), right, $\n), ":"),
- [ssl_cipher:erl_suite_definition(S)
+ [ssl_cipher:suite_definition(S)
|| S <- ssl_cipher:suites(tls_record:highest_protocol_version([])),
lists:member(ssl_cipher:openssl_suite_name(S), OpenSslSuites)
].
available_suites(Version) ->
- [ssl_cipher:erl_suite_definition(Suite) ||
+ [ssl_cipher:suite_definition(Suite) ||
Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
@@ -1274,10 +1309,18 @@ ecdh_dh_anonymous_suites(Version) ->
(_) ->
false
end}]).
+psk_suites({3,_} = Version) ->
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []);
psk_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []).
+ ssl:filter_cipher_suites(psk_suites(dtls_v1:corresponding_tls_version(Version)),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]).
-psk_anon_suites(Version) ->
+psk_anon_suites({3,_} = Version) ->
ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
[{key_exchange,
fun(psk) ->
@@ -1286,8 +1329,18 @@ psk_anon_suites(Version) ->
true;
(_) ->
false
+ end}]);
+
+psk_anon_suites(Version) ->
+ ssl:filter_cipher_suites(psk_anon_suites(dtls_v1:corresponding_tls_version(Version)),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
end}]).
+
srp_suites() ->
ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
@@ -1308,7 +1361,7 @@ srp_dss_suites() ->
false
end}]).
chacha_suites(Version) ->
- [ssl_cipher:erl_suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
+ [ssl_cipher:suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
rc4_suites(Version) ->
@@ -1338,7 +1391,7 @@ der_to_pem(File, Entries) ->
cipher_result(Socket, Result) ->
{ok, Info} = ssl:connection_information(Socket),
- Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}},
+ Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}},
ct:log("~p:~p~nSuccessfull connect: ~p~n", [?MODULE,?LINE, Result]),
%% Importante to send two packets here
%% to properly test "cipher state" handling
@@ -1450,10 +1503,13 @@ check_key_exchange_send_active(Socket, KeyEx) ->
send_recv_result_active(Socket).
check_key_exchange({KeyEx,_, _}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
true;
check_key_exchange({KeyEx,_,_,_}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
true;
check_key_exchange(KeyEx1, KeyEx2, Version) ->
+ ct:pal("Kex: ~p ~p", [KeyEx1, KeyEx2]),
case Version of
'tlsv1.2' ->
v_1_2_check(element(1, KeyEx1), KeyEx2);
@@ -1709,7 +1765,7 @@ filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_list(Cipher)->
filter_suites([ssl_cipher:openssl_suite(S) || S <- Ciphers],
AtomVersion);
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_binary(Cipher)->
- filter_suites([ssl_cipher:erl_suite_definition(S) || S <- Ciphers],
+ filter_suites([ssl_cipher:suite_definition(S) || S <- Ciphers],
AtomVersion);
filter_suites(Ciphers0, AtomVersion) ->
Version = tls_version(AtomVersion),
@@ -1721,7 +1777,7 @@ filter_suites(Ciphers0, AtomVersion) ->
++ ssl_cipher:srp_suites_anon()
++ ssl_cipher:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
- Supported2 = [ssl_cipher:erl_suite_definition(S) || S <- Supported1],
+ Supported2 = [ssl_cipher:suite_definition(S) || S <- Supported1],
[Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported2)].
-define(OPENSSL_QUIT, "Q\n").
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 10be907b4f..75d959accf 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 9.0
+SSL_VSN = 9.1
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 2b3860b76a..4541b4a463 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -155,6 +155,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index a808d3af55..eb0f7d24f0 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -722,7 +722,7 @@ handle_event(_, _, State, Data) ->
right before entering the initial state even though this
formally is not a state change.
In this case <c>OldState</c> will be the same as <c>State</c>,
- which can not happen for a subsequent state change,
+ which cannot happen for a subsequent state change,
but will happen when repeating the state enter call.
</p>
</desc>
@@ -1256,7 +1256,7 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
<c><anno>State</anno></c> is the current state
- and it can not be changed since the state callback
+ and it cannot be changed since the state callback
was called with a
<seealso marker="#type-state_enter"><em>state enter call</em></seealso>.
</p>
@@ -1922,7 +1922,7 @@ handle_event(_, _, State, Data) ->
<p>
If the function returns a failure <c>Reason</c>, the ongoing
upgrade fails and rolls back to the old release.
- Note that <c>Reason</c> can not be an <c>{ok,_,_}</c> tuple
+ Note that <c>Reason</c> cannot be an <c>{ok,_,_}</c> tuple
since that will be regarded as a
<c>{ok,NewState,NewData}</c> tuple,
and that a tuple matching <c>{ok,_}</c>
@@ -2208,7 +2208,7 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
<seealso marker="erts:erlang#throw/1"><c>throw</c></seealso>
to return the result, which can be useful.
For example to bail out with <c>throw(keep_state_and_data)</c>
- from deep within complex code that can not
+ from deep within complex code that cannot
return <c>{next_state,State,Data}</c> because
<c>State</c> or <c>Data</c> is no longer in scope.
</p>
diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml
index a225dea3b5..4c5199ca2b 100644
--- a/lib/stdlib/doc/src/maps.xml
+++ b/lib/stdlib/doc/src/maps.xml
@@ -35,9 +35,10 @@
<datatypes>
<datatype>
- <name name="iterator"/>
+ <name name="iterator" n_vars="2"/>
<desc>
- <p>An iterator representing the key value associations in a map.</p>
+ <p>An iterator representing the associations in a map with keys of type
+ <c><anno>Key</anno></c> and values of type <c><anno>Value</anno></c>.</p>
<p>Created using <seealso marker="#iterator-1"><c>maps:iterator/1</c></seealso>.</p>
<p>Consumed by <seealso marker="#next-1"><c>maps:next/1</c></seealso>,
<seealso marker="#filter-2"><c>maps:filter/2</c></seealso>,
@@ -45,6 +46,10 @@
<seealso marker="#map-2"><c>maps:map/2</c></seealso>.</p>
</desc>
</datatype>
+
+ <datatype>
+ <name name="iterator" n_vars="0"/>
+ </datatype>
</datatypes>
<funcs>
@@ -90,13 +95,13 @@
<name name="fold" arity="3"/>
<fsummary></fsummary>
<desc>
- <p>Calls <c>F(K, V, AccIn)</c> for every <c><anno>K</anno></c> to value
- <c><anno>V</anno></c> association in <c><anno>MapOrIter</anno></c> in
- any order. Function <c>fun F/3</c> must return a new
- accumulator, which is passed to the next successive call.
- This function returns the final value of the accumulator. The initial
- accumulator value <c><anno>Init</anno></c> is returned if the map is
- empty.</p>
+ <p>Calls <c>F(Key, Value, AccIn)</c> for every <c><anno>Key</anno></c>
+ to value <c><anno>Value</anno></c> association in
+ <c><anno>MapOrIter</anno></c> in any order. Function <c>fun F/3</c>
+ must return a new accumulator, which is passed to the next successive
+ call. This function returns the final value of the accumulator.
+ The initial accumulator value <c><anno>Init</anno></c> is returned
+ if the map is empty.</p>
<p>The call fails with a <c>{badmap,Map}</c> exception if
<c><anno>MapOrIter</anno></c> is not a map or valid iterator,
or with <c>badarg</c> if <c><anno>Fun</anno></c> is not a
@@ -234,11 +239,12 @@ none</code>
<fsummary></fsummary>
<desc>
<p>Produces a new map <c><anno>Map</anno></c> by calling function
- <c>fun F(K, V1)</c> for every <c><anno>K</anno></c> to value
- <c><anno>V1</anno></c> association in <c><anno>MapOrIter</anno></c> in
- any order. Function <c>fun F/2</c> must return value
- <c><anno>V2</anno></c> to be associated with key <c><anno>K</anno></c>
- for the new map <c><anno>Map</anno></c>.</p>
+ <c>fun F(Key, Value1)</c> for every <c><anno>Key</anno></c> to value
+ <c><anno>Value1</anno></c> association in
+ <c><anno>MapOrIter</anno></c> in any order. Function <c>fun Fun/2</c>
+ must return value <c><anno>Value2</anno></c> to be associated with
+ key <c><anno>Key</anno></c> for the new map
+ <c><anno>Map</anno></c>.</p>
<p>The call fails with a <c>{badmap,Map}</c> exception if
<c><anno>MapOrIter</anno></c> is not a map or valid iterator,
or with <c>badarg</c> if <c><anno>Fun</anno></c> is not a
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 611bfe73e0..8b6de03f5f 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -31,6 +31,23 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 3.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug that could cause a crash when formatting a
+ list of non-characters using the control sequences
+ <c>p</c> or <c>P</c> and limiting the output with the
+ option <c>chars_limit</c>. </p>
+ <p>
+ Own Id: OTP-15159</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -3642,7 +3659,7 @@
you use erlang:halt/2 with an integer first argument and
an option list containing {flush,false} as the second
argument. Note that now is flushing not dependant of the
- exit code, and you can not only flush async threads
+ exit code, and you cannot only flush async threads
operations which we deemed as a strange behaviour anyway.
</p>
<p>Also, erlang:halt/1,2 has gotten a new feature: If the
@@ -4156,9 +4173,9 @@
Supervisors should not save child-specs for temporary
processes when they terminate as they should not be
restarted. Saving the temporary child spec will result in
- that you can not start a new temporary process with the
+ that you cannot start a new temporary process with the
same child spec as an already terminated temporary
- process. Since R14B02 you can not restart a temporary
+ process. Since R14B02 you cannot restart a temporary
temporary process as arguments are no longer saved, it
has however always been semantically incorrect to restart
a temporary process. Thanks to Filipe David Manana for
diff --git a/lib/stdlib/include/assert.hrl b/lib/stdlib/include/assert.hrl
index 2ec89e7d8a..28d25c6589 100644
--- a/lib/stdlib/include/assert.hrl
+++ b/lib/stdlib/include/assert.hrl
@@ -140,7 +140,7 @@
-endif.
%% This is mostly a convenience which gives more detailed reports.
-%% Note: Guard is a guarded pattern, and can not be used for value.
+%% Note: Guard is a guarded pattern, and cannot be used for value.
-ifdef(NOASSERT).
-define(assertMatch(Guard, Expr), ok).
-define(assertMatch(Guard, Expr, Comment), ok).
@@ -289,7 +289,7 @@
end).
-endif.
-%% Note: Class and Term are patterns, and can not be used for value.
+%% Note: Class and Term are patterns, and cannot be used for value.
%% Term can be a guarded pattern, but Class cannot.
-ifdef(NOASSERT).
-define(assertException(Class, Term, Expr), ok).
@@ -364,7 +364,7 @@
?assertException(throw, Term, Expr, Comment)).
%% This is the inverse case of assertException, for convenience.
-%% Note: Class and Term are patterns, and can not be used for value.
+%% Note: Class and Term are patterns, and cannot be used for value.
%% Both Class and Term can be guarded patterns.
-ifdef(NOASSERT).
-define(assertNotException(Class, Term, Expr), ok).
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index ef4c7d255c..01181b1097 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -690,30 +690,31 @@ chunk_to_data(debug_info=Id, Chunk, File, _Cs, AtomTable, Mod) ->
<<0:8,N:8,Mode0:N/binary,Rest/binary>> ->
Mode = binary_to_atom(Mode0, utf8),
Term = decrypt_chunk(Mode, Mod, File, Id, Rest),
- {AtomTable, {Id, Term}};
+ {AtomTable, {Id, anno_from_term(Term)}};
_ ->
case catch binary_to_term(Chunk) of
{'EXIT', _} ->
error({invalid_chunk, File, chunk_name_to_id(Id, File)});
Term ->
- {AtomTable, {Id, Term}}
+ {AtomTable, {Id, anno_from_term(Term)}}
end
end;
chunk_to_data(abstract_code=Id, Chunk, File, _Cs, AtomTable, Mod) ->
+ %% Before Erlang/OTP 20.0.
case Chunk of
<<>> ->
{AtomTable, {Id, no_abstract_code}};
<<0:8,N:8,Mode0:N/binary,Rest/binary>> ->
Mode = binary_to_atom(Mode0, utf8),
Term = decrypt_chunk(Mode, Mod, File, Id, Rest),
- {AtomTable, {Id, anno_from_term(Term)}};
+ {AtomTable, {Id, old_anno_from_term(Term)}};
_ ->
case catch binary_to_term(Chunk) of
{'EXIT', _} ->
error({invalid_chunk, File, chunk_name_to_id(Id, File)});
Term ->
try
- {AtomTable, {Id, anno_from_term(Term)}}
+ {AtomTable, {Id, old_anno_from_term(Term)}}
catch
_:_ ->
error({invalid_chunk, File,
@@ -947,14 +948,24 @@ decrypt_chunk(Type, Module, File, Id, Bin) ->
error({key_missing_or_invalid, File, Id})
end.
-anno_from_term({raw_abstract_v1, Forms}) ->
+old_anno_from_term({raw_abstract_v1, Forms}) ->
{raw_abstract_v1, anno_from_forms(Forms)};
-anno_from_term({Tag, Forms}) when Tag =:= abstract_v1; Tag =:= abstract_v2 ->
+old_anno_from_term({Tag, Forms}) when Tag =:= abstract_v1;
+ Tag =:= abstract_v2 ->
try {Tag, anno_from_forms(Forms)}
catch
_:_ ->
{Tag, Forms}
end;
+old_anno_from_term(T) ->
+ T.
+
+anno_from_term({debug_info_v1=Tag1, erl_abstract_code=Tag2, {Forms, Opts}}) ->
+ try {Tag1, Tag2, {anno_from_forms(Forms), Opts}}
+ catch
+ _:_ ->
+ {Tag1, Tag2, {Forms, Opts}}
+ end;
anno_from_term(T) ->
T.
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 31c0e60fe1..2066b2f60f 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -329,7 +329,8 @@ expr({'fun',Line,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs) ->
20 -> fun (A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) ->
eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T], Info) end;
_Other ->
- erlang:raise(error, {'argument_limit',{'fun',Line,Cs}},
+ L = erl_anno:location(Line),
+ erlang:raise(error, {'argument_limit',{'fun',L,to_terms(Cs)}},
?STACKTRACE)
end,
ret_expr(F, Bs, RBs);
@@ -381,7 +382,9 @@ expr({named_fun,Line,Name,Cs} = Ex, Bs, Lf, Ef, RBs) ->
eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T],
RF, Info) end;
_Other ->
- erlang:raise(error, {'argument_limit',{named_fun,Line,Name,Cs}},
+ L = erl_anno:location(Line),
+ erlang:raise(error, {'argument_limit',
+ {named_fun,L,Name,to_terms(Cs)}},
?STACKTRACE)
end,
ret_expr(F, Bs, RBs);
@@ -1092,7 +1095,7 @@ match(Pat, Term, Bs) ->
match(Pat, Term, Bs, BBs) ->
case catch match1(Pat, Term, Bs, BBs) of
invalid ->
- erlang:raise(error, {illegal_pattern,Pat}, ?STACKTRACE);
+ erlang:raise(error, {illegal_pattern,to_term(Pat)}, ?STACKTRACE);
Other ->
Other
end.
@@ -1288,6 +1291,12 @@ merge_bindings(Bs1, Bs2) ->
%% end
%% end, Bs2, Bs1).
+to_terms(Abstrs) ->
+ [to_term(Abstr) || Abstr <- Abstrs].
+
+to_term(Abstr) ->
+ erl_parse:anno_to_term(Abstr).
+
%% Substitute {value, A, Item} for {var, A, Var}, preserving A.
%% {value, A, Item} is a shell/erl_eval convention, and for example
%% the linter cannot handle it.
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index b311a843c2..939abaff00 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -74,6 +74,7 @@ guard_bif(element, 2) -> true;
guard_bif(float, 1) -> true;
guard_bif(floor, 1) -> true;
guard_bif(hd, 1) -> true;
+guard_bif(is_map_key, 2) -> true;
guard_bif(length, 1) -> true;
guard_bif(map_size, 1) -> true;
guard_bif(map_get, 2) -> true;
@@ -109,7 +110,6 @@ new_type_test(is_function, 2) -> true;
new_type_test(is_integer, 1) -> true;
new_type_test(is_list, 1) -> true;
new_type_test(is_map, 1) -> true;
-new_type_test(is_map_key, 2) -> true;
new_type_test(is_number, 1) -> true;
new_type_test(is_pid, 1) -> true;
new_type_test(is_port, 1) -> true;
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 3390cee8ae..9602f0bcd9 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -980,7 +980,7 @@ Erlang code.
-type af_unary_op(T) :: {'op', anno(), unary_op(), T}.
--type unary_op() :: '+' | '*' | 'bnot' | 'not'.
+-type unary_op() :: '+' | '-' | 'bnot' | 'not'.
%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}.
-type type_specifier_list() :: 'default' | [type_specifier(), ...].
diff --git a/lib/stdlib/src/erl_posix_msg.erl b/lib/stdlib/src/erl_posix_msg.erl
index 8959fea498..b9ed4a3a9d 100644
--- a/lib/stdlib/src/erl_posix_msg.erl
+++ b/lib/stdlib/src/erl_posix_msg.erl
@@ -81,9 +81,9 @@ message_1(el2hlt) -> <<"level 2 halted">>;
message_1(el2nsync) -> <<"level 2 not synchronized">>;
message_1(el3hlt) -> <<"level 3 halted">>;
message_1(el3rst) -> <<"level 3 reset">>;
-message_1(elibacc) -> <<"can not access a needed shared library">>;
+message_1(elibacc) -> <<"cannot access a needed shared library">>;
message_1(elibbad) -> <<"accessing a corrupted shared library">>;
-message_1(elibexec) -> <<"can not exec a shared library directly">>;
+message_1(elibexec) -> <<"cannot exec a shared library directly">>;
message_1(elibmax) ->
<<"attempting to link in more shared libraries than system limit">>;
message_1(elibscn) -> <<".lib section in a.out corrupted">>;
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 367dbefb82..dd302a2880 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
_ -> ?TEST(T)
end).
-define(EXPRS_TEST(L),
- [?TEST(E) || E <- L]).
+ _ = [?TEST(E) || E <- L]).
-define(TEST(T),
%% Assumes that erl_anno has been compiled with DEBUG=true.
%% erl_pp does not use the annoations, but test it anyway.
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 3a5aba60b4..8223a52873 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -178,11 +178,11 @@ fread(Cont, Chars, Format) ->
Data :: [term()].
format(Format, Args) ->
- case catch io_lib_format:fwrite(Format, Args) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec format(Format, Data, Options) -> chars() when
@@ -193,11 +193,11 @@ format(Format, Args) ->
CharsLimit :: chars_limit().
format(Format, Args, Options) ->
- case catch io_lib_format:fwrite(Format, Args, Options) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args, Options]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec scan_format(Format, Data) -> FormatList when
@@ -208,7 +208,9 @@ format(Format, Args, Options) ->
scan_format(Format, Args) ->
try io_lib_format:scan(Format, Args)
catch
- _:_ -> erlang:error(badarg, [Format, Args])
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec unscan_format(FormatList) -> {Format, Data} when
@@ -223,7 +225,12 @@ unscan_format(FormatList) ->
FormatList :: [char() | format_spec()].
build_text(FormatList) ->
- io_lib_format:build(FormatList).
+ try io_lib_format:build(FormatList)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList])
+ end.
-spec build_text(FormatList, Options) -> chars() when
FormatList :: [char() | format_spec()],
@@ -232,7 +239,23 @@ build_text(FormatList) ->
CharsLimit :: chars_limit().
build_text(FormatList, Options) ->
- io_lib_format:build(FormatList, Options).
+ try io_lib_format:build(FormatList, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList, Options])
+ end.
+
+%% Failure to load a module must not be labeled as badarg.
+%% C, R, and S are included so that the original error, which could be
+%% a bug in io_lib_format, can be found by tracing on
+%% test_modules_loaded/3.
+test_modules_loaded(_C, _R, _S) ->
+ Modules = [io_lib_format, io_lib_pretty, string, unicode],
+ case code:ensure_modules_loaded(Modules) of
+ ok -> ok;
+ Error -> erlang:error(Error)
+ end.
-spec print(Term) -> chars() when
Term :: term().
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index c814ab50d4..e247b00a04 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -38,18 +38,16 @@
%% and it also splits the handling of the control characters into two
%% parts.
--spec fwrite(Format, Data) -> FormatList when
+-spec fwrite(Format, Data) -> io_lib:chars() when
Format :: io:format(),
- Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()].
+ Data :: [term()].
fwrite(Format, Args) ->
build(scan(Format, Args)).
--spec fwrite(Format, Data, Options) -> FormatList when
+-spec fwrite(Format, Data, Options) -> io_lib:chars() when
Format :: io:format(),
Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()],
Options :: [Option],
Option :: {'chars_limit', CharsLimit},
CharsLimit :: io_lib:chars_limit().
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index dca1b37ef3..ba9d9e8434 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -722,7 +722,7 @@ printable_list(L, _D, T, latin1) when T < 0 ->
io_lib:printable_latin1_list(L);
printable_list(L, _D, T, Enc) when T >= 0 ->
case slice(L, tsub(T, 2)) of
- {prefix, ""} ->
+ false ->
false;
{prefix, Prefix} when Enc =:= latin1 ->
io_lib:printable_latin1_list(Prefix) andalso {true, Prefix};
@@ -738,11 +738,17 @@ printable_list(L, _D, T, _Uni) when T < 0->
io_lib:printable_list(L).
slice(L, N) ->
- case string:length(L) =< N of
+ try string:length(L) =< N of
true ->
all;
false ->
- {prefix, string:slice(L, 0, N)}
+ case string:slice(L, 0, N) of
+ "" ->
+ false;
+ Prefix ->
+ {prefix, Prefix}
+ end
+ catch _:_ -> false
end.
printable_bin0(Bin, D, T, Enc) ->
diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl
index 60463feec2..51965ddb57 100644
--- a/lib/stdlib/src/maps.erl
+++ b/lib/stdlib/src/maps.erl
@@ -21,7 +21,7 @@
-module(maps).
-export([get/3, filter/2,fold/3,
- map/2, size/1,
+ map/2, size/1, new/0,
update_with/3, update_with/4,
without/2, with/2,
iterator/1, next/1]).
@@ -29,13 +29,15 @@
%% BIFs
-export([get/2, find/2, from_list/1,
is_key/2, keys/1, merge/2,
- new/0, put/3, remove/2, take/2,
+ put/3, remove/2, take/2,
to_list/1, update/3, values/1]).
--opaque iterator() :: {term(), term(), iterator()}
- | none | nonempty_improper_list(integer(),map()).
+-opaque iterator(Key, Value) :: {Key, Value, iterator(Key, Value)} | none
+ | nonempty_improper_list(integer(), #{Key => Value}).
--export_type([iterator/0]).
+-type iterator() :: iterator(term(), term()).
+
+-export_type([iterator/2, iterator/0]).
-dialyzer({no_improper_lists, iterator/1}).
@@ -50,9 +52,7 @@
get(_,_) -> erlang:nif_error(undef).
-spec find(Key,Map) -> {ok, Value} | error when
- Key :: term(),
- Map :: map(),
- Value :: term().
+ Map :: #{Key => Value, _ => _}.
find(_,_) -> erlang:nif_error(undef).
@@ -75,9 +75,8 @@ is_key(_,_) -> erlang:nif_error(undef).
-spec keys(Map) -> Keys when
- Map :: map(),
- Keys :: [Key],
- Key :: term().
+ Map :: #{Key => _},
+ Keys :: [Key].
keys(_) -> erlang:nif_error(undef).
@@ -91,13 +90,6 @@ keys(_) -> erlang:nif_error(undef).
merge(_,_) -> erlang:nif_error(undef).
-
--spec new() -> Map when
- Map :: map().
-
-new() -> erlang:nif_error(undef).
-
-
%% Shadowed by erl_bif_types: maps:put/3
-spec put(Key,Value,Map1) -> Map2 when
Key :: term(),
@@ -116,17 +108,13 @@ put(_,_,_) -> erlang:nif_error(undef).
remove(_,_) -> erlang:nif_error(undef).
-spec take(Key,Map1) -> {Value,Map2} | error when
- Key :: term(),
- Map1 :: map(),
- Value :: term(),
- Map2 :: map().
+ Map1 :: #{Key => Value, _ => _},
+ Map2 :: #{_ => _}.
take(_,_) -> erlang:nif_error(undef).
-spec to_list(Map) -> [{Key,Value}] when
- Map :: map(),
- Key :: term(),
- Value :: term().
+ Map :: #{Key => Value}.
to_list(Map) when is_map(Map) ->
to_list_internal(erts_internal:map_next(0, Map, []));
@@ -140,79 +128,69 @@ to_list_internal(Acc) ->
%% Shadowed by erl_bif_types: maps:update/3
-spec update(Key,Value,Map1) -> Map2 when
- Key :: term(),
- Value :: term(),
- Map1 :: map(),
- Map2 :: map().
+ Map1 :: #{Key := _, _ => _},
+ Map2 :: #{Key := Value, _ => _}.
update(_,_,_) -> erlang:nif_error(undef).
-spec values(Map) -> Values when
- Map :: map(),
- Values :: [Value],
- Value :: term().
+ Map :: #{_ => Value},
+ Values :: [Value].
values(_) -> erlang:nif_error(undef).
%% End of BIFs
+-spec new() -> Map when
+ Map :: #{}.
+
+new() -> #{}.
+
-spec update_with(Key,Fun,Map1) -> Map2 when
- Key :: term(),
- Map1 :: map(),
- Map2 :: map(),
- Fun :: fun((Value1 :: term()) -> Value2 :: term()).
+ Map1 :: #{Key := Value1, _ => _},
+ Map2 :: #{Key := Value2, _ => _},
+ Fun :: fun((Value1) -> Value2).
update_with(Key,Fun,Map) when is_function(Fun,1), is_map(Map) ->
- try maps:get(Key,Map) of
- Val -> maps:update(Key,Fun(Val),Map)
- catch
- error:{badkey,_} ->
- erlang:error({badkey,Key},[Key,Fun,Map])
+ case Map of
+ #{Key := Value} -> Map#{Key := Fun(Value)};
+ #{} -> erlang:error({badkey,Key},[Key,Fun,Map])
end;
update_with(Key,Fun,Map) ->
erlang:error(error_type(Map),[Key,Fun,Map]).
-spec update_with(Key,Fun,Init,Map1) -> Map2 when
- Key :: term(),
- Map1 :: Map1,
- Map2 :: Map2,
- Fun :: fun((Value1 :: term()) -> Value2 :: term()),
- Init :: term().
+ Map1 :: #{Key => Value1, _ => _},
+ Map2 :: #{Key := Value2 | Init, _ => _},
+ Fun :: fun((Value1) -> Value2).
update_with(Key,Fun,Init,Map) when is_function(Fun,1), is_map(Map) ->
- case maps:find(Key,Map) of
- {ok,Val} -> maps:update(Key,Fun(Val),Map);
- error -> maps:put(Key,Init,Map)
+ case Map of
+ #{Key := Value} -> Map#{Key := Fun(Value)};
+ #{} -> Map#{Key => Init}
end;
update_with(Key,Fun,Init,Map) ->
erlang:error(error_type(Map),[Key,Fun,Init,Map]).
-spec get(Key, Map, Default) -> Value | Default when
- Key :: term(),
- Map :: map(),
- Value :: term(),
- Default :: term().
+ Map :: #{Key => Value, _ => _}.
get(Key,Map,Default) when is_map(Map) ->
- case maps:find(Key, Map) of
- {ok, Value} ->
- Value;
- error ->
- Default
+ case Map of
+ #{Key := Value} -> Value;
+ #{} -> Default
end;
get(Key,Map,Default) ->
erlang:error({badmap,Map},[Key,Map,Default]).
--spec filter(Pred,MapOrIter) -> Map when
+-spec filter(Pred, MapOrIter) -> Map when
Pred :: fun((Key, Value) -> boolean()),
- Key :: term(),
- Value :: term(),
- MapOrIter :: map() | iterator(),
- Map :: map().
+ MapOrIter :: #{Key => Value} | iterator(Key, Value),
+ Map :: #{Key => Value}.
filter(Pred,Map) when is_function(Pred,2), is_map(Map) ->
maps:from_list(filter_1(Pred, iterator(Map)));
@@ -235,14 +213,11 @@ filter_1(Pred, Iter) ->
end.
-spec fold(Fun,Init,MapOrIter) -> Acc when
- Fun :: fun((K, V, AccIn) -> AccOut),
+ Fun :: fun((Key, Value, AccIn) -> AccOut),
Init :: term(),
- Acc :: term(),
- AccIn :: term(),
- AccOut :: term(),
- MapOrIter :: map() | iterator(),
- K :: term(),
- V :: term().
+ Acc :: AccOut,
+ AccIn :: Init | AccOut,
+ MapOrIter :: #{Key => Value} | iterator(Key, Value).
fold(Fun,Init,Map) when is_function(Fun,3), is_map(Map) ->
fold_1(Fun,Init,iterator(Map));
@@ -260,12 +235,9 @@ fold_1(Fun, Acc, Iter) ->
end.
-spec map(Fun,MapOrIter) -> Map when
- Fun :: fun((K, V1) -> V2),
- MapOrIter :: map() | iterator(),
- Map :: map(),
- K :: term(),
- V1 :: term(),
- V2 :: term().
+ Fun :: fun((Key, Value1) -> Value2),
+ MapOrIter :: #{Key => Value1} | iterator(Key, Value1),
+ Map :: #{Key => Value2}.
map(Fun,Map) when is_function(Fun, 2), is_map(Map) ->
maps:from_list(map_1(Fun, iterator(Map)));
@@ -291,17 +263,15 @@ size(Val) ->
erlang:error({badmap,Val},[Val]).
-spec iterator(Map) -> Iterator when
- Map :: map(),
- Iterator :: iterator().
+ Map :: #{Key => Value},
+ Iterator :: iterator(Key, Value).
iterator(M) when is_map(M) -> [0 | M];
iterator(M) -> erlang:error({badmap, M}, [M]).
-spec next(Iterator) -> {Key, Value, NextIterator} | 'none' when
- Iterator :: iterator(),
- Key :: term(),
- Value :: term(),
- NextIterator :: iterator().
+ Iterator :: iterator(Key, Value),
+ NextIterator :: iterator(Key, Value).
next({K, V, I}) ->
{K, V, I};
next([Path | Map]) when is_integer(Path), is_map(Map) ->
@@ -318,29 +288,26 @@ next(Iter) ->
K :: term().
without(Ks,M) when is_list(Ks), is_map(M) ->
- lists:foldl(fun(K, M1) -> maps:remove(K, M1) end, M, Ks);
+ lists:foldl(fun maps:remove/2, M, Ks);
without(Ks,M) ->
erlang:error(error_type(M),[Ks,M]).
-spec with(Ks, Map1) -> Map2 when
Ks :: [K],
- Map1 :: map(),
- Map2 :: map(),
- K :: term().
+ Map1 :: #{K => V, _ => _},
+ Map2 :: #{K => V}.
with(Ks,Map1) when is_list(Ks), is_map(Map1) ->
- Fun = fun(K, List) ->
- case maps:find(K, Map1) of
- {ok, V} ->
- [{K, V} | List];
- error ->
- List
- end
- end,
- maps:from_list(lists:foldl(Fun, [], Ks));
+ maps:from_list(with_1(Ks, Map1));
with(Ks,M) ->
erlang:error(error_type(M),[Ks,M]).
+with_1([K|Ks], Map) ->
+ case Map of
+ #{K := V} -> [{K,V}|with_1(Ks, Map)];
+ #{} -> with_1(Ks, Map)
+ end;
+with_1([], _Map) -> [].
error_type(M) when is_map(M) -> badarg;
error_type(V) -> {badmap, V}.
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index 89a840be2d..d07c62500b 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -30,7 +30,7 @@
start/3, start/4, start/5, start_link/3, start_link/4, start_link/5,
hibernate/3,
init_ack/1, init_ack/2,
- init_p/3,init_p/5,format/1,format/2,format/3,report_cb/1,
+ init_p/3,init_p/5,format/1,format/2,format/3,report_cb/2,
initial_call/1,
translate_initial_call/1,
stop/1, stop/3]).
@@ -509,7 +509,7 @@ crash_report(Class, Reason, StartF, Stacktrace) ->
report=>[my_info(Class, Reason, StartF, Stacktrace),
linked_info(self())]},
#{domain=>[otp,sasl],
- report_cb=>fun proc_lib:report_cb/1,
+ report_cb=>fun proc_lib:report_cb/2,
logger_formatter=>#{title=>"CRASH REPORT"},
error_logger=>#{tag=>error_report,type=>crash_report}}).
@@ -750,14 +750,15 @@ check(Res) -> Res.
%%% Format a generated crash info structure.
%%% -----------------------------------------------------------
--spec report_cb(CrashReport) -> {Format,Args} when
- CrashReport :: #{label=>{proc_lib,crash},report=>[term()]},
- Format :: io:format(),
- Args :: [term()].
-report_cb(#{label:={proc_lib,crash},
- report:=CrashReport}) ->
- Depth = error_logger:get_format_depth(),
- get_format_and_args(CrashReport, utf8, Depth).
+-spec report_cb(CrashReport,FormatOpts) -> unicode:chardata() when
+ CrashReport :: #{label => {proc_lib,crash},
+ report => [term()]},
+ FormatOpts :: logger:report_cb_config().
+report_cb(#{label:={proc_lib,crash}, report:=CrashReport}, Extra) ->
+ Default = #{chars_limit => unlimited,
+ depth => unlimited,
+ encoding => latin1},
+ do_format(CrashReport, maps:merge(Default,Extra)).
-spec format(CrashReport) -> string() when
CrashReport :: [term()].
@@ -777,66 +778,47 @@ format(CrashReport, Encoding) ->
Depth :: unlimited | pos_integer().
format(CrashReport, Encoding, Depth) ->
- {F,A} = get_format_and_args(CrashReport, Encoding, Depth),
- lists:flatten(io_lib:format(F,A)).
+ do_format(CrashReport, #{chars_limit => unlimited,
+ depth => Depth,
+ encoding => Encoding}).
-get_format_and_args([OwnReport,LinkReport], Encoding, Depth) ->
- Extra = {Encoding,Depth},
+do_format([OwnReport,LinkReport], Extra) ->
MyIndent = " ",
- {OwnFormat,OwnArgs} = format_report(OwnReport, MyIndent, Extra, [], []),
- {LinkFormat,LinkArgs} = format_link_report(LinkReport, MyIndent, Extra, [], []),
- {" crasher:~n"++OwnFormat++" neighbours:~n"++LinkFormat,OwnArgs++LinkArgs}.
+ OwnFormat = format_report(OwnReport, MyIndent, Extra),
+ LinkFormat = format_link_report(LinkReport, MyIndent, Extra),
+ Str = io_lib:format(" crasher:~n~ts neighbours:~n~ts",
+ [OwnFormat, LinkFormat]),
+ lists:flatten(Str).
-format_link_report([], _Indent, _Extra, Format, Args) ->
- {lists:flatten(lists:reverse(Format)),lists:append(lists:reverse(Args))};
-format_link_report([Link|Reps], Indent, Extra, Format, Args) ->
+format_link_report([Link|Reps], Indent, Extra) ->
Rep = case Link of
{neighbour,Rep0} -> Rep0;
_ -> Link
end,
LinkIndent = [" ",Indent],
- {LinkFormat,LinkArgs} = format_report(Rep, LinkIndent, Extra, [], []),
- F = "~sneighbour:\n"++LinkFormat,
- A = [Indent|LinkArgs],
- format_link_report(Reps, Indent, Extra, [F|Format], [A|Args]);
-format_link_report(Rep, Indent, Extra, Format, Args) ->
- {F,A} = format_report(Rep, Indent, Extra, [], []),
- format_link_report([], Indent, Extra, [F|Format],[A|Args]).
-
-format_report([], _Indent, _Extra, Format, Args) ->
- {lists:flatten(lists:reverse(Format)),lists:append(lists:reverse(Args))};
-format_report([Rep|Reps], Indent, Extra, Format, Args) ->
- {F,A} = format_rep(Rep, Indent, Extra),
- format_report(Reps, Indent, Extra, [F|Format], [A|Args]);
-format_report(Rep, Indent, {Enc,unlimited}=Extra, Format, Args) ->
- {F,A} = {"~s~"++modifier(Enc)++"p~n", [Indent, Rep]},
- format_report([], Indent, Extra, [F|Format], [A|Args]);
-format_report(Rep, Indent, {Enc,Depth}=Extra, Format, Args) ->
- {F,A} = {"~s~"++modifier(Enc)++"P~n", [Indent, Rep, Depth]},
- format_report([], Indent, Extra, [F|Format], [A|Args]).
-
-format_rep({initial_call,InitialCall}, Indent, Extra) ->
- format_mfa(Indent, InitialCall, Extra);
-format_rep({error_info,{Class,Reason,StackTrace}}, _Indent, Extra) ->
- {lists:flatten(format_exception(Class, Reason, StackTrace, Extra)),[]};
-format_rep({Tag,Data}, Indent, Extra) ->
- format_tag(Indent, Tag, Data, Extra).
-
-format_mfa(Indent, {M,F,Args}=StartF, {Enc,_}=Extra) ->
- try
- A = length(Args),
- {lists:flatten([Indent,"initial call: ",atom_to_list(M),
- $:,to_string(F, Enc),$/,integer_to_list(A),"\n"]),[]}
- catch
- error:_ ->
- format_tag(Indent, initial_call, StartF, Extra)
- end.
-
-format_tag(Indent, Tag, Data, {Enc,Depth}) ->
- {P,Tl} = p(Enc, Depth),
- {"~s~p: ~80.18" ++ P ++ "\n", [Indent, Tag, Data|Tl]}.
+ [Indent,"neighbour:\n",format_report(Rep, LinkIndent, Extra)|
+ format_link_report(Reps, Indent, Extra)];
+format_link_report(Rep, Indent, Extra) ->
+ format_report(Rep, Indent, Extra).
+
+format_report(Rep, Indent, Extra) when is_list(Rep) ->
+ format_rep(Rep, Indent, Extra);
+format_report(Rep, Indent, #{encoding:=Enc,depth:=unlimited}) ->
+ io_lib:format("~s~"++modifier(Enc)++"p~n", [Indent, Rep]);
+format_report(Rep, Indent, #{encoding:=Enc,depth:=Depth}) ->
+ io_lib:format("~s~"++modifier(Enc)++"P~n", [Indent, Rep, Depth]).
+
+format_rep([{initial_call,InitialCall}|Rep], Indent, Extra) ->
+ [format_mfa(Indent, InitialCall, Extra)|format_rep(Rep, Indent, Extra)];
+format_rep([{error_info,{Class,Reason,StackTrace}}|Rep], Indent, Extra) ->
+ [format_exception(Class, Reason, StackTrace, Extra)|
+ format_rep(Rep, Indent, Extra)];
+format_rep([{Tag,Data}|Rep], Indent, Extra) ->
+ [format_tag(Indent, Tag, Data, Extra)|format_rep(Rep, Indent, Extra)];
+format_rep(_, _, _Extra) ->
+ [].
-format_exception(Class, Reason, StackTrace, {Enc,_}=Extra) ->
+format_exception(Class, Reason, StackTrace, #{encoding:=Enc}=Extra) ->
PF = pp_fun(Extra),
StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
%% EI = " exception: ",
@@ -844,17 +826,37 @@ format_exception(Class, Reason, StackTrace, {Enc,_}=Extra) ->
[EI, erl_error:format_exception(1+length(EI), Class, Reason,
StackTrace, StackFun, PF, Enc), "\n"].
+format_mfa(Indent, {M,F,Args}=StartF, #{encoding:=Enc}=Extra) ->
+ try
+ A = length(Args),
+ [Indent,"initial call: ",atom_to_list(M),$:,to_string(F, Enc),$/,
+ integer_to_list(A),"\n"]
+ catch
+ error:_ ->
+ format_tag(Indent, initial_call, StartF, Extra)
+ end.
+
to_string(A, latin1) ->
io_lib:write_atom_as_latin1(A);
to_string(A, _) ->
io_lib:write_atom(A).
-pp_fun({Enc,Depth}) ->
+pp_fun(#{encoding:=Enc,depth:=Depth,chars_limit:=Limit}) ->
{P,Tl} = p(Enc, Depth),
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
fun(Term, I) ->
- io_lib:format("~." ++ integer_to_list(I) ++ P, [Term|Tl])
+ io_lib:format("~." ++ integer_to_list(I) ++ P, [Term|Tl], Opts)
end.
+format_tag(Indent, Tag, Data, #{encoding:=Enc,depth:=Depth,chars_limit:=Limit}) ->
+ {P,Tl} = p(Enc, Depth),
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ io_lib:format("~s~p: ~80.18" ++ P ++ "\n", [Indent, Tag, Data|Tl], Opts).
+
p(Encoding, Depth) ->
{Letter, Tl} = case Depth of
unlimited -> {"p", []};
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 362e98006e..4951dc727b 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -486,7 +486,7 @@ uniform_real_s(Alg, Next, M0, BitNo, R1, V1, Bits) ->
{M1 * math:pow(2.0, BitNo - 56), {Alg, R1}};
BitNo =:= -1008 ->
%% Endgame
- %% For the last round we can not have 14 zeros or more
+ %% For the last round we cannot have 14 zeros or more
%% at the top of M1 because then we will underflow,
%% so we need at least 43 bits
if
diff --git a/lib/stdlib/src/uri_string.erl b/lib/stdlib/src/uri_string.erl
index f07307c039..d33dc89af8 100644
--- a/lib/stdlib/src/uri_string.erl
+++ b/lib/stdlib/src/uri_string.erl
@@ -415,7 +415,7 @@ transcode(URIString, Options) when is_list(URIString) ->
%% (application/x-www-form-urlencoded encoding algorithm)
%%-------------------------------------------------------------------------
-spec compose_query(QueryList) -> QueryString when
- QueryList :: [{unicode:chardata(), unicode:chardata()}],
+ QueryList :: [{unicode:chardata(), unicode:chardata() | true}],
QueryString :: uri_string()
| error().
compose_query(List) ->
@@ -423,7 +423,7 @@ compose_query(List) ->
-spec compose_query(QueryList, Options) -> QueryString when
- QueryList :: [{unicode:chardata(), unicode:chardata()}],
+ QueryList :: [{unicode:chardata(), unicode:chardata() | true}],
Options :: [{encoding, atom()}],
QueryString :: uri_string()
| error().
@@ -435,6 +435,11 @@ compose_query(List, Options) ->
throw:{error, Atom, RestData} -> {error, Atom, RestData}
end.
%%
+compose_query([{Key,true}|Rest], Options, IsList, Acc) ->
+ Separator = get_separator(Rest),
+ K = form_urlencode(Key, Options),
+ IsListNew = IsList orelse is_list(Key),
+ compose_query(Rest, Options, IsListNew, <<Acc/binary,K/binary,Separator/binary>>);
compose_query([{Key,Value}|Rest], Options, IsList, Acc) ->
Separator = get_separator(Rest),
K = form_urlencode(Key, Options),
@@ -454,7 +459,7 @@ compose_query([], _Options, IsList, Acc) ->
%%-------------------------------------------------------------------------
-spec dissect_query(QueryString) -> QueryList when
QueryString :: uri_string(),
- QueryList :: [{unicode:chardata(), unicode:chardata()}]
+ QueryList :: [{unicode:chardata(), unicode:chardata() | true}]
| error().
dissect_query(<<>>) ->
[];
@@ -1889,13 +1894,12 @@ dissect_query_key(<<$=,T/binary>>, IsList, Acc, Key, Value) ->
dissect_query_value(T, IsList, Acc, Key, Value);
dissect_query_key(<<"&#",T/binary>>, IsList, Acc, Key, Value) ->
dissect_query_key(T, IsList, Acc, <<Key/binary,"&#">>, Value);
-dissect_query_key(<<$&,_T/binary>>, _IsList, _Acc, _Key, _Value) ->
- throw({error, missing_value, "&"});
+dissect_query_key(T = <<$&,_/binary>>, IsList, Acc, Key, <<>>) ->
+ dissect_query_value(T, IsList, Acc, Key, true);
dissect_query_key(<<H,T/binary>>, IsList, Acc, Key, Value) ->
dissect_query_key(T, IsList, Acc, <<Key/binary,H>>, Value);
-dissect_query_key(B, _, _, _, _) ->
- throw({error, missing_value, B}).
-
+dissect_query_key(T = <<>>, IsList, Acc, Key, <<>>) ->
+ dissect_query_value(T, IsList, Acc, Key, true).
dissect_query_value(<<$&,T/binary>>, IsList, Acc, Key, Value) ->
K = form_urldecode(IsList, Key),
@@ -1908,9 +1912,10 @@ dissect_query_value(<<>>, IsList, Acc, Key, Value) ->
V = form_urldecode(IsList, Value),
lists:reverse([{K,V}|Acc]).
-
%% HTML 5.2 - 4.10.21.6 URL-encoded form data - WHATWG URL (10 Jan 2018) - UTF-8
%% HTML 5.0 - 4.10.22.6 URL-encoded form data - decoding (non UTF-8)
+form_urldecode(_, true) ->
+ true;
form_urldecode(true, B) ->
Result = base10_decode(form_urldecode(B, <<>>)),
convert_to_list(Result, utf8);
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 73219f8fd8..3597d6d94b 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -78,7 +78,7 @@ normal(Conf) when is_list(Conf) ->
BeamFile = Simple ++ ".beam",
simple_file(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
do_normal(Source, PrivDir, BeamFile, []),
@@ -95,7 +95,7 @@ normal(Conf) when is_list(Conf) ->
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
@@ -173,7 +173,7 @@ error(Conf) when is_list(Conf) ->
WrongFile = Simple ++ "foo.beam",
simple_file(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
{ok,_} = compile:file(Source, [{outdir,PrivDir},debug_info]),
ACopy = filename:join(PrivDir, "a_copy.beam"),
@@ -213,7 +213,7 @@ error(Conf) when is_list(Conf) ->
%% we have eliminated them.
ok = file:write_file(BeamFile, <<"FOR1",5:32,"BEAMfel">>),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
file:delete(Source),
file:delete(WrongFile),
@@ -273,7 +273,7 @@ cmp(Conf) when is_list(Conf) ->
{Source2D1, BeamFile2D1} = make_beam(Dir1, simple2, concat),
{SourceD2, BeamFileD2} = make_beam(Dir2, simple, concat),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% cmp
@@ -300,7 +300,7 @@ cmp(Conf) when is_list(Conf) ->
ver(not_a_directory, beam_lib:diff_dirs(foo, bar)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, Source2D1,
BeamFile2D1, SourceD2, BeamFileD2]),
@@ -321,7 +321,7 @@ cmp_literals(Conf) when is_list(Conf) ->
{SourceD1, BeamFileD1} = make_beam(Dir1, simple, constant),
{SourceD2, BeamFileD2} = make_beam(Dir2, simple, constant2),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% cmp
@@ -334,7 +334,7 @@ cmp_literals(Conf) when is_list(Conf) ->
ver(chunks_different, beam_lib:cmp(B1, B2)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, SourceD2, BeamFileD2]),
@@ -351,7 +351,7 @@ strip(Conf) when is_list(Conf) ->
{Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
{Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% strip binary
@@ -392,7 +392,7 @@ strip(Conf) when is_list(Conf) ->
(catch lines:t(atom)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1,
Source2D1, BeamFile2D1,
@@ -457,7 +457,7 @@ building(Conf) when is_list(Conf) ->
{SourceD1, BeamFileD1} = make_beam(Dir1, building, member),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% read all chunks
@@ -487,7 +487,7 @@ building(Conf) when is_list(Conf) ->
end, ChunkIds),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, BeamFileD2]),
file:del_dir(Dir1),
@@ -535,7 +535,7 @@ encrypted_abstr_1(Conf) ->
%% Avoid getting an extra port when crypto starts erl_ddll.
erl_ddll:start(),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
Key = "#a_crypto_key",
@@ -549,7 +549,7 @@ encrypted_abstr_1(Conf) ->
ok = crypto:stop(), %To get rid of extra ets tables.
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
@@ -658,7 +658,7 @@ encrypted_abstr_file_1(Conf) ->
%% Avoid getting an extra port when crypto starts erl_ddll.
erl_ddll:start(),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
Key = "Long And niCe 99Krypto Key",
@@ -676,7 +676,7 @@ encrypted_abstr_file_1(Conf) ->
file:delete(filename:join(PrivDir, ".erlang.crypt")),
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index a3e294ffea..10e1b75e0f 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -1372,7 +1372,7 @@ otp_8562(Config) when is_list(Config) ->
otp_8911(Config) when is_list(Config) ->
case test_server:is_cover() of
true ->
- {skip, "Testing cover, so can not run when cover is already running"};
+ {skip, "Testing cover, so cannot run when cover is already running"};
false ->
do_otp_8911(Config)
end.
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index f9ab83a120..c1613a7273 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2730,7 +2730,7 @@ bif_clash(Config) when is_list(Config) ->
[],
{errors,[{2,erl_lint,{call_to_redefined_old_bif,{size,1}}}],[]}},
- %% Verify that warnings can not be turned off in the old way.
+ %% Verify that warnings cannot be turned off in the old way.
{clash2,
<<"-export([t/1,size/1]).
t(X) ->
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 7a48d1d55e..fee8b204f4 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -6112,40 +6112,11 @@ etsmem() ->
ets:info(T,memory),ets:info(T,type)}
end, ets:all()),
- EtsAllocInfo = erlang:system_info({allocator,ets_alloc}),
+ EtsAllocSize = erts_debug:alloc_blocks_size(ets_alloc),
ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end,
- Mem =
- {ErlangMemoryEts,
- case EtsAllocInfo of
- false -> undefined;
- MemInfo ->
- CS = lists:foldl(
- fun ({instance, _, L}, Acc) ->
- {value,{mbcs,MBCS}} = lists:keysearch(mbcs, 1, L),
- {value,{sbcs,SBCS}} = lists:keysearch(sbcs, 1, L),
- NewAcc = [MBCS, SBCS | Acc],
- case lists:keysearch(mbcs_pool, 1, L) of
- {value,{mbcs_pool, MBCS_POOL}} ->
- [MBCS_POOL|NewAcc];
- _ -> NewAcc
- end
- end,
- [],
- MemInfo),
- lists:foldl(
- fun(L, {Bl0,BlSz0}) ->
- {value,BlTup} = lists:keysearch(blocks, 1, L),
- blocks = element(1, BlTup),
- Bl = element(2, BlTup),
- {value,BlSzTup} = lists:keysearch(blocks_size, 1, L),
- blocks_size = element(1, BlSzTup),
- BlSz = element(2, BlSzTup),
- {Bl0+Bl,BlSz0+BlSz}
- end, {0,0}, CS)
- end},
- {Mem,AllTabs}.
-
+ Mem = {ErlangMemoryEts, EtsAllocSize},
+ {Mem, AllTabs}.
verify_etsmem(MI) ->
wait_for_test_procs(),
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 91fe1133f6..f097552e8c 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -31,7 +31,8 @@
otp_10836/1, io_lib_width_too_small/1,
io_with_huge_message_queue/1, format_string/1,
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
- otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1]).
+ otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
+ otp_15159/1]).
-export([pretty/2, trf/3]).
@@ -63,7 +64,7 @@ all() ->
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
io_lib_width_too_small, io_with_huge_message_queue,
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
- otp_14285, limit_term, otp_14983, otp_15103].
+ otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159].
%% Error cases for output.
error_1(Config) when is_list(Config) ->
@@ -2633,3 +2634,16 @@ otp_15103(_Config) ->
"[{a,\n b,\n c},\n {a,\n b,...},\n {a,...},\n {...}|...]" =
lists:flatten(S5),
ok.
+
+otp_15159(_Config) ->
+ "[atom]" =
+ lists:flatten(io_lib:format("~p", [[atom]], [{chars_limit,5}])),
+ ok.
+
+otp_15076(_Config) ->
+ {'EXIT', {badarg, _}} = (catch io_lib:format("~c", [a])),
+ L = io_lib:scan_format("~c", [a]),
+ {"~c", [a]} = io_lib:unscan_format(L),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L)),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])),
+ ok.
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index 837ab4e97e..af94fc79bc 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -1679,7 +1679,7 @@ make_fun() ->
receive {Pid, Fun} -> Fun end.
make_fun(Pid) ->
- Pid ! {self(), fun make_fun/1}.
+ Pid ! {self(), fun (X) -> {X, Pid} end}.
fun_pid(Fun) ->
erlang:fun_info(Fun, pid).
diff --git a/lib/stdlib/test/stdlib.spec b/lib/stdlib/test/stdlib.spec
index 9c625091a8..4de7c1a0eb 100644
--- a/lib/stdlib/test/stdlib.spec
+++ b/lib/stdlib/test/stdlib.spec
@@ -1,4 +1,4 @@
{suites,"../stdlib_test",all}.
{skip_groups,"../stdlib_test",stdlib_bench_SUITE,
- [base64,gen_server,gen_statem,unicode],
+ [binary,base64,gen_server,gen_statem,unicode],
"Benchmark only"}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE.erl b/lib/stdlib/test/stdlib_bench_SUITE.erl
index 2364e8376f..b937eeb06a 100644
--- a/lib/stdlib/test/stdlib_bench_SUITE.erl
+++ b/lib/stdlib/test/stdlib_bench_SUITE.erl
@@ -29,7 +29,7 @@ suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
all() ->
- [{group,unicode},{group,base64},
+ [{group,unicode},{group,base64},{group,binary},
{group,gen_server},{group,gen_statem},
{group,gen_server_comparison},{group,gen_statem_comparison}].
@@ -38,6 +38,11 @@ groups() ->
[norm_nfc_list, norm_nfc_deep_l, norm_nfc_binary,
string_lexemes_list, string_lexemes_binary
]},
+ {binary, [{repeat, 5}],
+ [match_single_pattern_no_match,
+ matches_single_pattern_no_match,
+ matches_single_pattern_eventual_match,
+ matches_single_pattern_frequent_match]},
{base64,[{repeat,5}],
[decode_binary, decode_binary_to_string,
decode_list, decode_list_to_string,
@@ -157,41 +162,59 @@ norm_data(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+match_single_pattern_no_match(_Config) ->
+ Binary = binary:copy(<<"ugbcfuysabfuqyfikgfsdalpaskfhgjsdgfjwsalp">>, 1000000),
+ comment(test(binary, match, [Binary, <<"o">>])).
+
+matches_single_pattern_no_match(_Config) ->
+ Binary = binary:copy(<<"ugbcfuysabfuqyfikgfsdalpaskfhgjsdgfjwsalp">>, 1000000),
+ comment(test(binary, matches, [Binary, <<"o">>])).
+
+matches_single_pattern_eventual_match(_Config) ->
+ Binary = binary:copy(<<"ugbcfuysabfuqyfikgfsdalpaskfhgjsdgfjwsal\n">>, 1000000),
+ comment(test(binary, matches, [Binary, <<"\n">>])).
+
+matches_single_pattern_frequent_match(_Config) ->
+ Binary = binary:copy(<<"abc\n">>, 1000000),
+ comment(test(binary, matches, [Binary, <<"abc">>])).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
decode_binary(_Config) ->
- comment(test(decode, encoded_binary())).
+ comment(test(base64, decode, [encoded_binary()])).
decode_binary_to_string(_Config) ->
- comment(test(decode_to_string, encoded_binary())).
+ comment(test(base64, decode_to_string, [encoded_binary()])).
decode_list(_Config) ->
- comment(test(decode, encoded_list())).
+ comment(test(base64, decode, [encoded_list()])).
decode_list_to_string(_Config) ->
- comment(test(decode_to_string, encoded_list())).
+ comment(test(base64, decode_to_string, [encoded_list()])).
encode_binary(_Config) ->
- comment(test(encode, binary())).
+ comment(test(base64, encode, [binary()])).
encode_binary_to_string(_Config) ->
- comment(test(encode_to_string, binary())).
+ comment(test(base64, encode_to_string, [binary()])).
encode_list(_Config) ->
- comment(test(encode, list())).
+ comment(test(base64, encode, [list()])).
encode_list_to_string(_Config) ->
- comment(test(encode_to_string, list())).
+ comment(test(base64, encode_to_string, [list()])).
mime_binary_decode(_Config) ->
- comment(test(mime_decode, encoded_binary())).
+ comment(test(base64, mime_decode, [encoded_binary()])).
mime_binary_decode_to_string(_Config) ->
- comment(test(mime_decode_to_string, encoded_binary())).
+ comment(test(base64, mime_decode_to_string, [encoded_binary()])).
mime_list_decode(_Config) ->
- comment(test(mime_decode, encoded_list())).
+ comment(test(base64, mime_decode, [encoded_list()])).
mime_list_decode_to_string(_Config) ->
- comment(test(mime_decode_to_string, encoded_list())).
+ comment(test(base64, mime_decode_to_string, [encoded_list()])).
-define(SIZE, 10000).
-define(N, 1000).
@@ -209,15 +232,15 @@ binary() ->
list() ->
random_byte_list(?SIZE).
-test(Func, Data) ->
- F = fun() -> loop(?N, Func, Data) end,
+test(Mod, Fun, Args) ->
+ F = fun() -> loop(?N, Mod, Fun, Args) end,
{Time, ok} = timer:tc(fun() -> lspawn(F) end),
- report_base64(Time).
+ report_mfa(Time, Mod).
-loop(0, _F, _D) -> garbage_collect(), ok;
-loop(N, F, D) ->
- _ = base64:F(D),
- loop(N - 1, F, D).
+loop(0, _M, _F, _A) -> garbage_collect(), ok;
+loop(N, M, F, A) ->
+ _ = apply(M, F, A),
+ loop(N - 1, M, F, A).
lspawn(Fun) ->
{Pid, Ref} = spawn_monitor(fun() -> exit(Fun()) end),
@@ -225,10 +248,10 @@ lspawn(Fun) ->
{'DOWN', Ref, process, Pid, Rep} -> Rep
end.
-report_base64(Time) ->
+report_mfa(Time, Mod) ->
Tps = round((?N*1000000)/Time),
ct_event:notify(#event{name = benchmark_data,
- data = [{suite, "stdlib_base64"},
+ data = [{suite, "stdlib_" ++ atom_to_list(Mod)},
{value, Tps}]}),
Tps.
diff --git a/lib/stdlib/test/uri_string_SUITE.erl b/lib/stdlib/test/uri_string_SUITE.erl
index 4fc0d76be8..ddaead9c7c 100644
--- a/lib/stdlib/test/uri_string_SUITE.erl
+++ b/lib/stdlib/test/uri_string_SUITE.erl
@@ -862,9 +862,11 @@ transcode_negative(_Config) ->
compose_query(_Config) ->
[] = uri_string:compose_query([]),
"foo=1&bar=2" = uri_string:compose_query([{<<"foo">>,"1"}, {"bar", "2"}]),
+ "foo=1&bar" = uri_string:compose_query([{<<"foo">>,"1"}, {"bar", true}]),
"foo=1&b%C3%A4r=2" = uri_string:compose_query([{"foo","1"}, {"bär", "2"}],[{encoding,utf8}]),
"foo=1&b%C3%A4r=2" = uri_string:compose_query([{"foo","1"}, {"bär", "2"}],[{encoding,unicode}]),
"foo=1&b%E4r=2" = uri_string:compose_query([{"foo","1"}, {"bär", "2"}],[{encoding,latin1}]),
+ "foo&b%E4r=2" = uri_string:compose_query([{"foo",true}, {"bär", "2"}],[{encoding,latin1}]),
"foo+bar=1&%E5%90%88=2" = uri_string:compose_query([{"foo bar","1"}, {"合", "2"}]),
"foo+bar=1&%26%2321512%3B=2" =
uri_string:compose_query([{"foo bar","1"}, {"合", "2"}],[{encoding,latin1}]),
@@ -906,11 +908,13 @@ dissect_query(_Config) ->
[{"föo bar","1"},{"ö","2"}] =
uri_string:dissect_query("föo+bar=1&%C3%B6=2"),
[{<<"föo bar"/utf8>>,<<"1">>},{<<"ö"/utf8>>,<<"2">>}] =
- uri_string:dissect_query(<<"föo+bar=1&%C3%B6=2"/utf8>>).
+ uri_string:dissect_query(<<"föo+bar=1&%C3%B6=2"/utf8>>),
+ [{"foo1",true},{"bar","2"}] =
+ uri_string:dissect_query("foo1&bar=2"),
+ [{<<"foo1">>,<<"1">>},{<<"bar">>,true}] =
+ uri_string:dissect_query(<<"foo1=1&bar">>).
dissect_query_negative(_Config) ->
- {error,missing_value,"&"} =
- uri_string:dissect_query("foo1&bar=2"),
{error,invalid_percent_encoding,"%XX%B6"} = uri_string:dissect_query("foo=%XX%B6&amp;bar=2"),
{error,invalid_input,[153]} =
uri_string:dissect_query("foo=%99%B6&amp;bar=2"),
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 0525b2de0b..1d833430f1 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.5
+STDLIB_VSN = 3.5.1
diff --git a/lib/syntax_tools/doc/src/Makefile b/lib/syntax_tools/doc/src/Makefile
index 797f9c265f..d953287bad 100644
--- a/lib/syntax_tools/doc/src/Makefile
+++ b/lib/syntax_tools/doc/src/Makefile
@@ -125,6 +125,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index 7ba90a6495..44944e57c3 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -33,29 +33,28 @@
application.</p>
<section><title>Syntax_Tools 2.1.5</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
+ <section><title>Improvements and New Features</title>
<list>
<item>
- <p> Fix a bug regarding reverting map types. </p>
<p>
- Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ Update to use the new string api instead of the old.</p>
+ <p>
+ Own Id: OTP-15036</p>
</item>
</list>
</section>
+</section>
-
- <section><title>Improvements and New Features</title>
+<section><title>Syntax_Tools 2.1.4.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
+ <p> Fix a bug regarding reverting map types. </p>
<p>
- Update to use the new string api instead of the old.</p>
- <p>
- Own Id: OTP-15036</p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
</item>
</list>
</section>
-
</section>
<section><title>Syntax_Tools 2.1.4</title>
@@ -109,6 +108,20 @@
</section>
+<section><title>Syntax_Tools 2.1.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 029f1e88ac..758aff32fd 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -7223,7 +7223,7 @@ macro_arguments(Node) ->
%% @doc Returns the syntax tree corresponding to an Erlang term.
%% `Term' must be a literal term, i.e., one that can be
%% represented as a source code literal. Thus, it may not contain a
-%% process identifier, port, reference, binary or function value as a
+%% process identifier, port, reference or function value as a
%% subterm. The function recognises printable strings, in order to get a
%% compact and readable representation. Evaluation fails with reason
%% `badarg' if `Term' is not a literal term.
@@ -7257,6 +7257,13 @@ abstract(T) when is_map(T) ->
|| {Key,Value} <- maps:to_list(T)]);
abstract(T) when is_binary(T) ->
binary([binary_field(integer(B)) || B <- binary_to_list(T)]);
+abstract(T) when is_bitstring(T) ->
+ S = bit_size(T),
+ ByteS = S div 8,
+ BitS = S rem 8,
+ <<Bin:ByteS/binary, I:BitS>> = T,
+ binary([binary_field(integer(B)) || B <- binary_to_list(Bin)]
+ ++ [binary_field(integer(I), integer(BitS), [])]);
abstract(T) ->
erlang:error({badarg, T}).
@@ -7332,15 +7339,20 @@ concrete(Node) ->
Node0 -> maps:merge(concrete(Node0),M0)
end;
binary ->
- Fs = [revert_binary_field(
- binary_field(binary_field_body(F),
- case binary_field_size(F) of
- none -> none;
- S ->
- revert(S)
- end,
- binary_field_types(F)))
- || F <- binary_fields(Node)],
+ Fs = [begin
+ B = binary_field_body(F),
+ {Body, Size} =
+ case type(B) of
+ size_qualifier ->
+ {size_qualifier_body(B),
+ size_qualifier_argument(B)};
+ _ ->
+ {B, none}
+ end,
+ revert_binary_field(
+ binary_field(Body, Size, binary_field_types(F)))
+ end
+ || F <- binary_fields(Node)],
{value, B, _} =
eval_bits:expr_grp(Fs, [],
fun(F, _) ->
@@ -7413,7 +7425,14 @@ is_literal(T) ->
is_literal_binary_field(F) ->
case binary_field_types(F) of
- [] -> is_literal(binary_field_body(F));
+ [] -> B = binary_field_body(F),
+ case type(B) of
+ size_qualifier ->
+ is_literal(size_qualifier_body(B)) andalso
+ is_literal(size_qualifier_argument(B));
+ _ ->
+ is_literal(B)
+ end;
_ -> false
end.
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index ced0dba3e2..352165893f 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -1981,7 +1981,7 @@ analyze_application(Node) ->
%%
%% @see analyze_type_name/1
--type typeName() :: atom() | {module(), atom(), arity()} | {atom(), arity()}.
+-type typeName() :: atom() | {module(), {atom(), arity()}} | {atom(), arity()}.
-spec analyze_type_application(erl_syntax:syntaxTree()) -> typeName().
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index 16e3511734..b712b77e9f 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -660,7 +660,7 @@ merge_files1(Files, Opts) ->
%% transitions), code replacement is expected to be detected. Then, if
%% we in the merged code do not check at these points if the
%% <em>target</em> module (the result of the merge) has been replaced,
-%% we can not be sure in general that we will be able to do code
+%% we cannot be sure in general that we will be able to do code
%% replacement of the merged state machine - it could run forever
%% without detecting the code change. Therefore, all such calls must
%% remain remote-calls (detecting code changes), but may call the target
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index c8e6448d37..4cddf8f0c3 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -157,6 +157,7 @@ t_abstract_type(Config) when is_list(Config) ->
{[$a,$b,$c],string},
{"hello world",string},
{<<1,2,3>>,binary},
+ {<<1,2,3:4>>,binary},
{#{a=>1,"b"=>2},map_expr},
{#{#{i=>1}=>1,"b"=>#{v=>2}},map_expr},
{{a,b,c},tuple}]),
diff --git a/lib/tftp/doc/src/Makefile b/lib/tftp/doc/src/Makefile
index a2fdcf6325..5d76799e41 100644
--- a/lib/tftp/doc/src/Makefile
+++ b/lib/tftp/doc/src/Makefile
@@ -103,6 +103,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/tftp/doc/src/tftp.xml b/lib/tftp/doc/src/tftp.xml
index 481e5446ad..4ed54bc462 100644
--- a/lib/tftp/doc/src/tftp.xml
+++ b/lib/tftp/doc/src/tftp.xml
@@ -150,7 +150,7 @@
<tag><c>{logger, Module}</c></tag>
<item>
- <p><c>Module = module()()</c></p>
+ <p><c>Module = module()</c></p>
<p>Callback module for customized logging of errors, warnings, and
info messages. The callback module must implement the
@@ -220,7 +220,7 @@
<name>info(daemons) -> [{Pid, Options}]</name>
<fsummary>Returns information about all daemons.</fsummary>
<type>
- <v>Pid = [pid()()]</v>
+ <v>Pid = [pid()]</v>
<v>Options = [option()]</v>
<v>Reason = term()</v>
</type>
@@ -233,7 +233,7 @@
<name>info(servers) -> [{Pid, Options}]</name>
<fsummary>Returns information about all servers.</fsummary>
<type>
- <v>Pid = [pid()()]</v>
+ <v>Pid = [pid()]</v>
<v>Options = [option()]</v>
<v>Reason = term()</v>
</type>
diff --git a/lib/tools/doc/src/Makefile b/lib/tools/doc/src/Makefile
index 001c31a443..5ff4fe3113 100644
--- a/lib/tools/doc/src/Makefile
+++ b/lib/tools/doc/src/Makefile
@@ -120,6 +120,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
diff --git a/lib/tools/doc/src/cover.xml b/lib/tools/doc/src/cover.xml
index 15cd784253..6c6b20aad8 100644
--- a/lib/tools/doc/src/cover.xml
+++ b/lib/tools/doc/src/cover.xml
@@ -234,7 +234,7 @@
<c>{already_cover_compiled,no_beam_found,Module}</c> is
returned.</p>
<p><c>{error,BeamFile}</c> is returned if the compiled code
- can not be loaded on the node.</p>
+ cannot be loaded on the node.</p>
<p>If a list of <c>ModFiles</c> is given as input, a list
of <c>Result</c> will be returned. The order of the returned
list is undefined.</p>
@@ -470,7 +470,7 @@
<p>Exports the current coverage data for <c>Module</c> to the
file <c>ExportFile</c>. It is recommended to name the
<c>ExportFile</c> with the extension <c>.coverdata</c>, since
- other filenames can not be read by the web based interface to
+ other filenames cannot be read by the web based interface to
cover.</p>
<p>If <c>Module</c> is not given, data for all Cover compiled
or earlier imported modules is exported.</p>
@@ -496,7 +496,7 @@
<p>Coverage data from several export files can be imported
into one system. The coverage data is then added up when
analysing.</p>
- <p>Coverage data for a module can not be imported from the
+ <p>Coverage data for a module cannot be imported from the
same file twice unless the module is first reset or
compiled. The check is based on the filename, so you can
easily fool the system by renaming your export file.</p>
diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml
index 9fd9332373..79bacb2927 100644
--- a/lib/tools/doc/src/instrument.xml
+++ b/lib/tools/doc/src/instrument.xml
@@ -111,15 +111,18 @@
default, but this can be configured an a per-allocator basis with the
<seealso marker="erts:erts_alloc#M_atags"><c>+M&lt;S&gt;atags</c>
</seealso> emulator option.</p>
- <p>If tagged allocations are not enabled on any of the specified
- allocator types, the call will fail with
- <c>{error, not_enabled}</c>.</p>
+ <p>If the specified allocator types are not enabled, the call will fail
+ with <c>{error, not_enabled}</c>.</p>
<p>The following options can be used:</p>
<taglist>
<tag><c>allocator_types</c></tag>
<item>
- <p>The allocator types that will be searched. Defaults to all
- <c>alloc_util</c> allocators.</p>
+ <p>The allocator types that will be searched. Note that blocks can
+ move freely between allocator types, so restricting the search to
+ certain allocators may return unexpected types (e.g. process
+ heaps when searching binary_alloc), or hide blocks that were
+ migrated out.</p>
+ <p>Defaults to all <c>alloc_util</c> allocators.</p>
</item>
<tag><c>scheduler_ids</c></tag>
<item>
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 3211132254..242a5abe72 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -77,6 +77,7 @@
;;; Code:
(eval-when-compile (require 'cl))
+(eval-when-compile (require 'align))
;; Variables:
@@ -1405,6 +1406,19 @@ Other commands:
(add-function :before-until (local 'eldoc-documentation-function)
#'erldoc-eldoc-function))
(run-hooks 'erlang-mode-hook)
+
+ ;; Align maps.
+ (add-to-list 'align-rules-list
+ '(erlang-maps
+ (regexp . "\\(\\s-*\\)\\(=>\\)\\s-*")
+ (modes . '(erlang-mode))
+ (repeat . t)))
+ ;; Align records and :: specs
+ (add-to-list 'align-rules-list
+ '(erlang-record-specs
+ (regexp . "\\(\\s-*\\)\\(=\\).*\\(::\\)*\\s-*")
+ (modes . '(erlang-mode))
+ (repeat . t)))
(if (zerop (buffer-size))
(run-hooks 'erlang-new-file-hook)))
diff --git a/lib/tools/priv/styles.css b/lib/tools/priv/styles.css
new file mode 100644
index 0000000000..e10e94e3ad
--- /dev/null
+++ b/lib/tools/priv/styles.css
@@ -0,0 +1,91 @@
+body {
+ font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #000;
+ border-top: 2px solid #ddd;
+ background-color: #fff;
+
+ min-height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+h1 {
+ width: 100%;
+ border-bottom: 1px solid #eee;
+ margin-bottom: 0;
+ font-weight: 100;
+ font-size: 1.1em;
+ letter-spacing: 1px;
+}
+
+h1 code {
+ font-size: 0.96em;
+}
+
+code {
+ font: 12px monospace;
+}
+
+footer {
+ background: #eee;
+ width: 100%;
+ padding: 10px 0;
+ text-align: right;
+ border-top: 1px solid #ddd;
+ display: flex;
+ flex: 1;
+ order: 2;
+ justify-content: center;
+}
+
+table {
+ width: 100%;
+ margin-top: 10px;
+ border-collapse: collapse;
+ border: 1px solid #cbcbcb;
+ color: #000;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+}
+table thead {
+ display: none;
+}
+table td.line,
+table td.hits {
+ width: 20px;
+ background: #eaeaea;
+ text-align: center;
+ font-size: 11px;
+ padding: 0 10px;
+ color: #949494;
+}
+table td.hits {
+ width: 10px;
+ padding: 2px 5px;
+ color: rgba(0, 0, 0, 0.6);
+ background-color: #f0f0f0;
+}
+tr.miss td.line,
+tr.miss td.hits {
+ background-color: #ffdce0;
+ border-color: #fdaeb7;
+}
+tr.miss td {
+ background-color: #ffeef0;
+}
+tr.hit td.line,
+tr.hit td.hits {
+ background-color: #cdffd8;
+ border-color: #bef5cb;
+}
+tr.hit td {
+ background-color: #e6ffed;
+}
+td.source {
+ padding-left: 15px;
+ line-height: 15px;
+ white-space: pre;
+ font: 12px monospace;
+}
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index 032bd612db..a869ae6a00 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -72,6 +72,9 @@ APP_TARGET = $(EBIN)/$(APP_FILE)
APPUP_SRC = $(APPUP_FILE).src
APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+PRIVDIR = ../priv
+CSS = $(PRIVDIR)/styles.css
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -110,5 +113,7 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
"$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(CSS) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index bf5faa165d..337d9d637a 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -144,6 +144,8 @@
end).
-define(SPAWN_DBG(Tag,Value),put(Tag,Value)).
+-define(STYLESHEET, "styles.css").
+-define(TOOLS_APP, tools).
-include_lib("stdlib/include/ms_transform.hrl").
@@ -2415,20 +2417,8 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
case file:open(OutFile, [write,raw,delayed_write]) of
{ok, OutFd} ->
Enc = encoding(ErlFile),
- if HTML ->
- Header =
- ["<!DOCTYPE HTML PUBLIC "
- "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<html>\n"
- "<head>\n"
- "<meta http-equiv=\"Content-Type\""
- " content=\"text/html; charset=",
- html_encoding(Enc),"\"/>\n"
- "<title>",OutFile,"</title>\n"
- "</head>"
- "<body style='background-color: white;"
- " color: black'>\n"
- "<pre>\n"],
+ if HTML ->
+ Header = create_header(OutFile, Enc),
H1Bin = unicode:characters_to_binary(Header,Enc,Enc),
ok = file:write(OutFd,H1Bin);
true -> ok
@@ -2445,14 +2435,19 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
string:pad(integer_to_list(Mi), 2, leading, $0),
string:pad(integer_to_list(S), 2, leading, $0)]),
- H2Bin = unicode:characters_to_binary(
- ["File generated from ",ErlFile," by COVER ",
- Timestamp,"\n\n"
- "**************************************"
- "**************************************"
- "\n\n"],
- Enc, Enc),
- ok = file:write(OutFd, H2Bin),
+ OutFileInfo =
+ if HTML ->
+ create_footer(ErlFile, Timestamp);
+ true ->
+ ["File generated from ",ErlFile," by COVER ",
+ Timestamp, "\n\n",
+ "**************************************"
+ "**************************************"
+ "\n\n"]
+ end,
+
+ H2Bin = unicode:characters_to_binary(OutFileInfo,Enc,Enc),
+ ok = file:write(OutFd, H2Bin),
Pattern = {#bump{module=Module,line='$1',_='_'},'$2'},
MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}],
@@ -2462,7 +2457,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
print_lines(Module, CovLines, InFd, OutFd, 1, HTML),
if HTML ->
- ok = file:write(OutFd, "</pre>\n</body>\n</html>\n");
+ ok = file:write(OutFd, close_html());
true -> ok
end,
@@ -2497,12 +2492,11 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
case CovLines of
[{L,N}|CovLines1] ->
if N=:=0, HTML=:=true ->
- LineNoNL = Line -- "\n",
- Str = " 0",
- %%Str = string:pad("0", 6, leading, $\s),
- RedLine = ["<font color=red>",Str,fill1(),
- LineNoNL,"</font>\n"],
- ok = file:write(OutFd, RedLine);
+ MissedLine = table_row("miss", Line, L, N),
+ ok = file:write(OutFd, MissedLine);
+ HTML=:=true ->
+ HitLine = table_row("hit", Line, L, N),
+ ok = file:write(OutFd, HitLine);
N < 1000000 ->
Str = string:pad(integer_to_list(N), 6, leading, $\s),
ok = file:write(OutFd, [Str,fill1(),Line]);
@@ -2515,7 +2509,11 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
end,
print_lines(Module, CovLines1, InFd, OutFd, L+1, HTML);
_ -> %Including comment lines
- ok = file:write(OutFd, [tab(),Line]),
+ NonCoveredContent =
+ if HTML -> table_row(Line, L);
+ true -> [tab(),Line]
+ end,
+ ok = file:write(OutFd, NonCoveredContent),
print_lines(Module, CovLines, InFd, OutFd, L+1, HTML)
end
end.
@@ -2525,6 +2523,59 @@ fill1() -> "..| ".
fill2() -> ".| ".
fill3() -> "| ".
+%% HTML sections
+create_header(OutFile, Enc) ->
+ ["<!doctype html>\n"
+ "<html>\n"
+ "<head>\n"
+ "<meta charset=\"",html_encoding(Enc),"\">\n"
+ "<title>",OutFile,"</title>\n"
+ "<style>"] ++
+ read_stylesheet() ++
+ ["</style>\n",
+ "</head>\n"
+ "<body>\n"
+ "<h1><code>",OutFile,"</code></h1>\n"].
+
+create_footer(ErlFile, Timestamp) ->
+ ["<footer><p>File generated from <code>",ErlFile,
+ "</code> by <a href=\"http://erlang.org/doc/man/cover.html\">cover</a> at ",
+ Timestamp,"</p></footer>\n<table>\n<tbody>\n"].
+
+close_html() ->
+ ["</tbody>\n",
+ "<thead>\n",
+ "<tr>\n",
+ "<th>Line</th>\n",
+ "<th>Hits</th>\n",
+ "<th>Source</th>\n",
+ "</tr>\n",
+ "</thead>\n",
+ "</table>\n",
+ "</body>\n"
+ "</html>\n"].
+
+table_row(CssClass, Line, L, N) ->
+ ["<tr class=\"",CssClass,"\">\n", table_data(Line, L, N)].
+table_row(Line, L) ->
+ ["<tr>\n", table_data(Line, L, "")].
+
+table_data(Line, L, N) ->
+ LineNoNL = Line -- "\n",
+ ["<td class=\"line\" id=\"L",integer_to_list(L),"\">",
+ integer_to_list(L),
+ "</td>\n",
+ "<td class=\"hits\">",maybe_integer_to_list(N),"</td>\n",
+ "<td class=\"source\"><code>",LineNoNL,"</code></td>\n</tr>\n"].
+
+maybe_integer_to_list(N) when is_integer(N) -> integer_to_list(N);
+maybe_integer_to_list(_) -> "".
+
+read_stylesheet() ->
+ PrivDir = code:priv_dir(?TOOLS_APP),
+ {ok, Css} = file:read_file(filename:join(PrivDir, ?STYLESHEET)),
+ [Css].
+
%%%--Export--------------------------------------------------------------
do_export(Module, OutFile, From, State) ->
case file:open(OutFile,[write,binary,raw,delayed_write]) of
diff --git a/lib/tools/test/instrument_SUITE.erl b/lib/tools/test/instrument_SUITE.erl
index 8c521b2e1a..33259df58f 100644
--- a/lib/tools/test/instrument_SUITE.erl
+++ b/lib/tools/test/instrument_SUITE.erl
@@ -77,6 +77,8 @@ allocations_ramv(Config) when is_list(Config) ->
verify_allocations_disabled(_AllocType, Result) ->
verify_allocations_disabled(Result).
+verify_allocations_disabled({ok, {_HistStart, _UnscannedBytes, Allocs}}) ->
+ true = Allocs =:= #{};
verify_allocations_disabled({error, not_enabled}) ->
ok.
@@ -91,6 +93,13 @@ verify_allocations_enabled(_AllocType, Result) ->
verify_allocations_enabled({ok, {_HistStart, _UnscannedBytes, Allocs}}) ->
true = Allocs =/= #{}.
+verify_allocations_output(#{}, {ok, {_, _, Allocs}}) when Allocs =:= #{} ->
+ %% This happens when the allocator is enabled but tagging is disabled. If
+ %% there's an error that causes Allocs to always be empty when enabled it
+ %% will be caught by verify_allocations_enabled.
+ ok;
+verify_allocations_output(#{}, {error, not_enabled}) ->
+ ok;
verify_allocations_output(#{ histogram_start := HistStart,
histogram_width := HistWidth },
{ok, {HistStart, _UnscannedBytes, ByOrigin}}) ->
@@ -124,8 +133,6 @@ verify_allocations_output(#{ histogram_start := HistStart,
[BlockCount, GenTotalBlockCount])
end,
- ok;
-verify_allocations_output(#{}, {error, not_enabled}) ->
ok.
%% %% %% %% %% %%
@@ -214,7 +221,8 @@ verify_carriers_output(#{ histogram_start := HistStart,
ct:fail("Carrier count is ~p, expected at least ~p (SBC).",
[CarrierCount, GenSBCCount]);
CarrierCount >= GenSBCCount ->
- ok
+ ct:pal("Found ~p carriers, required at least ~p (SBC)." ,
+ [CarrierCount, GenSBCCount])
end,
ok;
@@ -292,9 +300,19 @@ start_slave(Args) ->
MicroSecs = erlang:monotonic_time(),
Name = "instr" ++ integer_to_list(MicroSecs),
Pa = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(list_to_atom(Name),
- slave,
- [{args, "-pa " ++ Pa ++ " " ++ Args}]),
+
+ %% We pass arguments through ZFLAGS as the nightly tests rotate
+ %% +Meamax/+Meamin which breaks the _enabled and _disabled tests unless
+ %% overridden.
+ ZFlags = os:getenv("ERL_ZFLAGS", ""),
+ {ok, Node} = try
+ os:putenv("ERL_ZFLAGS", ZFlags ++ [" " | Args]),
+ test_server:start_node(list_to_atom(Name),
+ slave,
+ [{args, "-pa " ++ Pa}])
+ after
+ os:putenv("ERL_ZFLAGS", ZFlags)
+ end,
Node.
generate_test_blocks() ->
@@ -309,8 +327,9 @@ generate_test_blocks() ->
MBCs = [<<I, 0:64/unit:8>> ||
I <- lists:seq(1, ?GENERATED_MBC_BLOCK_COUNT)],
Runner ! Ref,
- receive after infinity -> ok end,
- unreachable ! {SBCs, MBCs}
+ receive
+ gurka -> gaffel ! {SBCs, MBCs}
+ end
end),
receive
Ref -> ok
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 018f632948..4ec75f7962 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -2233,18 +2233,18 @@ variables(Conf) when is_list(Conf) ->
{{error, _, _}, _} = xref_base:variables(S108, [{verbose,false}]),
{ok, S109} = xref_base:set_library_path(S108, [], [{verbose,false}]),
- Tabs = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
{ok, S110} = eval("Eplus := closure E, TT := Eplus",
'closure()', S109),
{{ok, [{user, ['Eplus','TT']}]}, S111} = xref_base:variables(S110),
{ok, S112} = xref_base:forget(S111, ['TT','Eplus']),
- true = Tabs =:= length(ets:all()),
+ true = NoOfTables =:= erlang:system_info(ets_count),
{ok, NS0} = eval("Eplus := closure E", 'closure()', S112),
{{ok, [{user, ['Eplus']}]}, NS} = xref_base:variables(NS0),
ok = xref_base:delete(NS),
- true = Tabs =:= length(ets:all()),
+ true = NoOfTables =:= erlang:system_info(ets_count),
ok = file:delete(Beam),
ok.
diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c
index 8b8c625971..c9d299e0df 100644
--- a/lib/wx/c_src/wxe_driver.c
+++ b/lib/wx/c_src/wxe_driver.c
@@ -38,10 +38,8 @@
#define TEMP_BINARY_SIZE 512
-static ErlDrvData wxe_driver_start(ErlDrvPort port, char *buff);
-static int wxe_driver_load(void);
+static ErlDrvData wxe_driver_start(ErlDrvPort port, char *command);
static void wxe_driver_stop(ErlDrvData handle);
-static void wxe_driver_unload(void);
static ErlDrvSSizeT wxe_driver_control(ErlDrvData handle,
unsigned int command,
char* buf, ErlDrvSizeT count,
@@ -63,30 +61,30 @@ char * erl_wx_privdir;
** The driver struct
*/
static ErlDrvEntry wxe_driver_entry = {
- wxe_driver_load, /* F_PTR init, called at loading */
- wxe_driver_start, /* L_PTR start, called when port is opened */
- wxe_driver_stop, /* F_PTR stop, called when port is closed */
- NULL, /* F_PTR output, called when erlang has sent */
- NULL, /* F_PTR ready_input, called when input descriptor
- ready */
- NULL, /* F_PTR ready_output, called when output
- descriptor ready */
- "wxe_driver", /* char *driver_name, the argument to open_port */
- wxe_driver_unload, /* F_PTR finish, called when unloaded */
- NULL, /* void * that is not used (BC) */
- wxe_driver_control, /* F_PTR control, port_control callback */
- NULL, /* F_PTR timeout, reserved */
- standard_outputv, /* F_PTR outputv, reserved */
- NULL, /* async */
- NULL, /* flush */
- wxe_driver_call, /* call */
- NULL, /* Event */
+ NULL, /* F_PTR init, called at loading */
+ wxe_driver_start, /* L_PTR start, called when port is opened */
+ wxe_driver_stop, /* F_PTR stop, called when port is closed */
+ NULL, /* F_PTR output, called when erlang has sent */
+ NULL, /* F_PTR ready_input, called when
+ input descriptor ready */
+ NULL, /* F_PTR ready_output, called when
+ output descriptor ready */
+ "wxe_driver", /* char *driver_name, the argument to open_port */
+ NULL, /* F_PTR finish, called when unloaded */
+ NULL, /* void * that is not used (BC) */
+ wxe_driver_control, /* F_PTR control, port_control callback */
+ NULL, /* F_PTR timeout, reserved */
+ standard_outputv, /* F_PTR outputv, reserved */
+ NULL, /* async */
+ NULL, /* flush */
+ wxe_driver_call, /* call */
+ NULL, /* Event */
ERL_DRV_EXTENDED_MARKER,
ERL_DRV_EXTENDED_MAJOR_VERSION,
ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */
- NULL, /* Reserved Handle */
- wxe_process_died, /* Process Exited */
+ ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */
+ NULL, /* Reserved Handle */
+ wxe_process_died, /* Process Exited */
};
DRIVER_INIT(wxe_driver)
@@ -94,60 +92,56 @@ DRIVER_INIT(wxe_driver)
return &wxe_driver_entry;
}
-int wxe_driver_load()
-{
- if(load_native_gui())
- return 0;
- else
- return -1;
-}
-
ErlDrvPort WXE_DRV_PORT_HANDLE = 0;
ErlDrvTermData WXE_DRV_PORT = 0;
static ErlDrvData
-wxe_driver_start(ErlDrvPort port, char *buff)
-{
- wxe_data *data;
-
- data = (wxe_data *) malloc(sizeof(wxe_data));
- wxe_debug = 0;
-
- if (data == NULL) {
- fprintf(stderr, " Couldn't alloc mem\r\n");
- return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
- } else {
- ErlDrvTermData term_port = driver_mk_port(port);
- set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
- data->driver_data = NULL;
- data->bin = (WXEBinRef*) driver_alloc(sizeof(WXEBinRef)*DEF_BINS);
- data->bin[0].from = 0;
- data->bin[1].from = 0;
- data->bin[2].from = 0;
- data->max_bins = DEF_BINS;
- data->port_handle = port;
- data->port = term_port;
- data->pdl = driver_pdl_create(port);
- if(WXE_DRV_PORT_HANDLE == 0) {
- for(; *buff != 32; buff++);
- buff++;
- erl_wx_privdir = strdup(buff);
-
- WXE_DRV_PORT_HANDLE = port;
- WXE_DRV_PORT = term_port;
- wxe_master = data;
- if(!(start_native_gui(data) == 1))
- return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
- } else {
- meta_command(CREATE_PORT,data);
- }
- return (ErlDrvData) data;
- }
+wxe_driver_start(ErlDrvPort port, char *command)
+{
+ wxe_data *data;
+
+ data = (wxe_data *) malloc(sizeof(wxe_data));
+ wxe_debug = 0;
+
+ if (data == NULL) {
+ fprintf(stderr, " Couldn't alloc mem\r\n");
+ return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
+ } else {
+ ErlDrvTermData term_port = driver_mk_port(port);
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+ data->driver_data = NULL;
+ data->bin = (WXEBinRef*) driver_alloc(sizeof(WXEBinRef)*DEF_BINS);
+ data->bin[0].from = 0;
+ data->bin[1].from = 0;
+ data->bin[2].from = 0;
+ data->max_bins = DEF_BINS;
+ data->port_handle = port;
+ data->port = term_port;
+ data->pdl = driver_pdl_create(port);
+ if(WXE_DRV_PORT_HANDLE == 0) {
+ char *first_space = strchr(command, ' ');
+ if (first_space) {
+ char *priv_dir = first_space + 1;
+ erl_wx_privdir = strdup(priv_dir);
+
+ WXE_DRV_PORT_HANDLE = port;
+ WXE_DRV_PORT = term_port;
+ wxe_master = data;
+ if(start_native_gui(data) != 1)
+ return ERL_DRV_ERROR_GENERAL; /* ENOMEM */
+ } else {
+ return ERL_DRV_ERROR_BADARG;
+ }
+ } else {
+ meta_command(CREATE_PORT, data);
+ }
+ return (ErlDrvData) data;
+ }
}
static void
wxe_driver_stop(ErlDrvData handle)
-{
+{
wxe_data *sd = ((wxe_data *)handle);
if(sd->port_handle != WXE_DRV_PORT_HANDLE) {
// fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__);
@@ -155,18 +149,11 @@ wxe_driver_stop(ErlDrvData handle)
} else {
// fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__);
stop_native_gui(wxe_master);
- unload_native_gui();
free(wxe_master);
wxe_master = NULL;
}
}
-static void
-wxe_driver_unload(void)
-{
- // fprintf(stderr, "%s:%d: UNLOAD \r\n", __FILE__,__LINE__);
-}
-
static ErlDrvSSizeT
wxe_driver_control(ErlDrvData handle, unsigned op,
char* buf, ErlDrvSizeT count,
@@ -194,7 +181,7 @@ wxe_driver_call(ErlDrvData handle, unsigned int command,
if (len > rlen)
*res = driver_alloc(len);
memcpy((void *) *res, (void *) buf, len);
- return len;
+ return len;
}
@@ -219,20 +206,20 @@ standard_outputv(ErlDrvData drv_data, ErlIOVec* ev)
int i, max;
for(i = 0; i < sd->max_bins; i++) {
- if(sd->bin[i].from == 0) {
- binref = &sd->bin[i];
- break;
- }
+ if(sd->bin[i].from == 0) {
+ binref = &sd->bin[i];
+ break;
+ }
}
if(binref == NULL) { /* realloc */
- max = sd->max_bins + DEF_BINS;
- driver_realloc(sd->bin, sizeof(WXEBinRef)*max);
- for(i=sd->max_bins; i < max; i++) {
- sd->bin[i].from = 0;
- }
- binref = &sd->bin[sd->max_bins];
- sd->max_bins = max;
+ max = sd->max_bins + DEF_BINS;
+ driver_realloc(sd->bin, sizeof(WXEBinRef)*max);
+ for(i=sd->max_bins; i < max; i++) {
+ sd->bin[i].from = 0;
+ }
+ binref = &sd->bin[sd->max_bins];
+ sd->max_bins = max;
}
if(ev->size > 0) {
diff --git a/lib/wx/c_src/wxe_driver.h b/lib/wx/c_src/wxe_driver.h
index f9bca049c8..8b4ce2b804 100644
--- a/lib/wx/c_src/wxe_driver.h
+++ b/lib/wx/c_src/wxe_driver.h
@@ -56,10 +56,8 @@ typedef struct wxe_data_def {
void init_glexts(wxe_data*);
-int load_native_gui();
int start_native_gui(wxe_data *sd);
void stop_native_gui(wxe_data *sd);
-void unload_native_gui();
#define FUNC_CALL 13
#define CREATE_PORT 14
diff --git a/lib/wx/c_src/wxe_main.cpp b/lib/wx/c_src/wxe_main.cpp
index c7565e33bd..5b65d8a59b 100644
--- a/lib/wx/c_src/wxe_main.cpp
+++ b/lib/wx/c_src/wxe_main.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,15 +59,9 @@ void *wxe_main_loop(void * );
* START AND STOP of driver thread
* ************************************************************/
-int load_native_gui()
-{
- return 1;
-}
-
int start_native_gui(wxe_data *sd)
{
int res;
- ErlDrvThreadOpts *opts = NULL;
wxe_status_m = erl_drv_mutex_create((char *) "wxe_status_m");
wxe_status_c = erl_drv_cond_create((char *)"wxe_status_c");
@@ -79,7 +73,7 @@ int start_native_gui(wxe_data *sd)
res = erl_drv_steal_main_thread((char *)"wxwidgets",
&wxe_thread,wxe_main_loop,(void *) sd->pdl,NULL);
#else
- opts = erl_drv_thread_opts_create((char *)"wx thread");
+ ErlDrvThreadOpts *opts = erl_drv_thread_opts_create((char *)"wx thread");
opts->suggested_stack_size = 8192;
res = erl_drv_thread_create((char *)"wxwidgets",
&wxe_thread,wxe_main_loop,(void *) sd->pdl,opts);
@@ -116,11 +110,6 @@ void stop_native_gui(wxe_data *sd)
erl_drv_cond_destroy(wxe_batch_locker_c);
}
-void unload_native_gui()
-{
-
-}
-
/* ************************************************************
* wxWidgets Thread
* ************************************************************/
diff --git a/lib/wx/doc/overview.edoc b/lib/wx/doc/overview.edoc
index 054016f515..843a9c1320 100644
--- a/lib/wx/doc/overview.edoc
+++ b/lib/wx/doc/overview.edoc
@@ -218,7 +218,7 @@ the <em>fun</em> returns.
The callbacks are always invoked by another process and have
exclusive usage of the GUI when invoked. This means that a callback <em>fun</em>
-can not use the process dictionary and should not make calls to other
+cannot use the process dictionary and should not make calls to other
processes. Calls to another process inside a callback <em>fun</em> may cause a
deadlock if the other process is waiting on completion of his call to
the GUI.
diff --git a/lib/wx/doc/src/Makefile b/lib/wx/doc/src/Makefile
index 70555ae1eb..f66d63f63b 100644
--- a/lib/wx/doc/src/Makefile
+++ b/lib/wx/doc/src/Makefile
@@ -121,7 +121,8 @@ $(XML_CHAPTER_FILES:%=$(XMLDIR)/%): ../overview.edoc
debug opt:
clean clean_docs:
- rm -rf $(HTMLDIR)/*
+ rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
diff --git a/lib/wx/examples/demo/ex_graphicsContext.erl b/lib/wx/examples/demo/ex_graphicsContext.erl
index 1193578037..1e6ffce18d 100644
--- a/lib/wx/examples/demo/ex_graphicsContext.erl
+++ b/lib/wx/examples/demo/ex_graphicsContext.erl
@@ -74,7 +74,7 @@ do_init(Config) ->
pen = Pen, brush = Brush, font = Font}}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Sync events i.e. from callbacks must return ok, it can not return a new state.
+%% Sync events i.e. from callbacks must return ok, it cannot return a new state.
%% Do the redrawing here.
handle_sync_event(#wx{event = #wxPaint{}},_,
#state{win=Win, pen = Pen, brush = Brush, font = Font}) ->
diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl
index 7ecd9b7283..1cc194d569 100644
--- a/lib/wx/test/wx_event_SUITE.erl
+++ b/lib/wx/test/wx_event_SUITE.erl
@@ -347,9 +347,9 @@ connect_in_callback(Config) ->
%% such that new events are not fired until the previous
%% callback have returned.
- %% That means that a callback can not wait for other events
+ %% That means that a callback cannot wait for other events
%% in receive since they will not come.
- %% It also means that you can not attach a new callback directly from
+ %% It also means that you cannot attach a new callback directly from
%% the callback since that callback will be removed when the temporary
%% process that executes the outer callback (may) die(s) before the callback
%% is invoked
diff --git a/lib/wx/test/wxt b/lib/wx/test/wxt
index e720ed94f4..1343542366 100755
--- a/lib/wx/test/wxt
+++ b/lib/wx/test/wxt
@@ -18,7 +18,7 @@
#
# %CopyrightEnd%
#
-# Usage: mt <args to erlang startup script>
+# Usage: wxt <args to erlang startup script>
log=test_log_$$
latest=test_log_latest
@@ -27,7 +27,7 @@ erlcmd="erl -sname test_server -smp -pa ../ebin $p $args -wx_test_verbose true -
echo "Give the following command in order to see the outcome:"
echo ""
-echo " less test_log$$"
+echo " less $log"
rm "$latest" 2>/dev/null
ln -s "$log" "$latest"
diff --git a/lib/xmerl/doc/src/Makefile b/lib/xmerl/doc/src/Makefile
index d87677d0a7..0def492246 100644
--- a/lib/xmerl/doc/src/Makefile
+++ b/lib/xmerl/doc/src/Makefile
@@ -140,6 +140,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(XMERL_XML_FILES)
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index a1f6ad4e2c..a7538180e6 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -279,7 +279,7 @@ int_file_decl(F, Options,_ExtCharset) ->
%% @spec string(Text::list()) -> {xmlElement(),Rest}
%% Rest = list()
-%% @equiv string(Test, [])
+%% @equiv string(Text, [])
string(Str) ->
string(Str, []).
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
index c2533248d1..0379c18214 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
@@ -276,7 +276,7 @@
</exception>
<exception name="UpgradeNotPossibleException">
- <description>Before an upgrade is started it was found that the upgrade can not take place. A possible reason is that the upgrade package that is running in the node is not in the upgrade window of this upgrade package. </description>
+ <description>Before an upgrade is started it was found that the upgrade cannot take place. A possible reason is that the upgrade package that is running in the node is not in the upgrade window of this upgrade package. </description>
<exceptionParameter name="message">
<dataType>
<string/>
@@ -1703,7 +1703,7 @@ Example:
<exception name="NoSuchAttributeException">
<description>Exception thrown when an MO attribute is requested to be accessed but the access
-method for the is not defined (the attribute can not be accessed)</description>
+method for the is not defined (the attribute cannot be accessed)</description>
</exception>
<exception name="MoCardinalityViolationException">
@@ -3125,7 +3125,7 @@ active = Synchronization is used in system clock generation.
<description>RefState can have the following values:
failed = synchronization reference is not capable to perform its required tasks.
degraded = capability of synchronization reference to perform its required tasks is degraded e.g. because of signal level degradation. This value is only applicable for traffic carrying (ET physical path termination) synchronization references. Note: attribute degradationIsFault controls whether synchronization reference degradation is interpreted as a synchronization reference fault or not.
-lossOfTracking = system clock regulation algorithm on TU board can not follow the 8kHz synchronization reference signal either because of the poor quality of the signal or because of a HW fault at TU board. If all synchronization references repeatedly end up to state lossOfTracking, fault is likely in TU HW.
+lossOfTracking = system clock regulation algorithm on TU board cannot follow the 8kHz synchronization reference signal either because of the poor quality of the signal or because of a HW fault at TU board. If all synchronization references repeatedly end up to state lossOfTracking, fault is likely in TU HW.
ok = synchronization reference is capable of performing its required tasks.
</description>
<enumMember name="failed">
@@ -11270,7 +11270,7 @@ Note! This action requires a transaction.</description>
The changing of the IP address with operation assignIpAddress might cause interruption of the communication if the network management tool is connected via the ethernet link.
-Note: The EthernetLink MO can not be deleted!
+Note: The EthernetLink MO cannot be deleted!
Note: The performance monitoring counters in the EthernetLink MO has a "Wrap-around time" of approximately 2 hours.
</description>
@@ -11532,8 +11532,8 @@ Note! This action requires a transaction.</description>
<description>This MO holds the IP routing table.
The IpRoutingTable MO is automatically created when the Ip MO is created.
-The IpRoutingTable MO can not be created manually.
-The IpRoutingTable MO can not be deleted.
+The IpRoutingTable MO cannot be created manually.
+The IpRoutingTable MO cannot be deleted.
</description>
<systemCreated/>
<attribute name="userLabel">
@@ -12967,7 +12967,7 @@ Note! When using fractional atm, timeslot 1 must be a part of the fraction.
Note! ETM1 does not support EPD and PPD
-Note! ETM1 does not have a proper buffer management. Thus fairness of UBR+ traffic can not be guaranteed and shaping on UBR+ traffic is not possible.
+Note! ETM1 does not have a proper buffer management. Thus fairness of UBR+ traffic cannot be guaranteed and shaping on UBR+ traffic is not possible.
Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 per port.
</description>
@@ -13371,7 +13371,7 @@ Struct element description :
-Date is in string format, max length is 40. Format for date is: weekday month date hour:min:seconds year.
-Status is in string format, max length is 40.
-Note! The identity can not be the same as name. Identity should contain the product identity.
+Note! The identity cannot be the same as name. Identity should contain the product identity.
</description>
@@ -13562,7 +13562,7 @@ Note! For comment and operatorName spaces (' ') are also allowed within the stri
This action does not require a transaction.
-Note! The configurationVersionName and identity can not be the same. The identity should be the product identity.
+Note! The configurationVersionName and identity cannot be the same. The identity should be the product identity.
</description>
<returnType>
<void/>
@@ -17367,7 +17367,7 @@ NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
<attribute name="mtp2ProfileItuId">
<description>Reference to a Mtp2ProfileItu MO.
-Note: The bitRate can not be changed.</description>
+Note: The bitRate cannot be changed.</description>
<mandatory/>
<noNotification/>
<dataType>
@@ -17566,7 +17566,7 @@ NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
<attribute name="mtp2ProfileAnsiId">
<description>Reference to a Mtp2ProfileAnsi MO.
-Note: The bitRate can not be changed.</description>
+Note: The bitRate cannot be changed.</description>
<mandatory/>
<noNotification/>
<dataType>
@@ -21777,7 +21777,7 @@ Each E1/DS1/J1 channel can suport up to 2 VP connections.
The ET-MC41 board support one biderectional F4/F5 PM flow per E1 channel.
-Note! The ETMC41 supports IMA. However the E1 ports being part of the same IMA group can not be selected randomly.
+Note! The ETMC41 supports IMA. However the E1 ports being part of the same IMA group cannot be selected randomly.
Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 / port
@@ -21883,7 +21883,7 @@ NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.
<attribute name="mtp2ProfileChinaId">
<description>Reference to a Mtp2ProfileChina MO.
-Note: The bitRate can not be changed.</description>
+Note: The bitRate cannot be changed.</description>
<mandatory/>
<noNotification/>
<dataType>
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
index 3b5d8ae2ad..3b9ccac0f4 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
@@ -276,7 +276,7 @@
</exception>
<exception name="UpgradeNotPossibleException">
- <description>Before an upgrade is started it was found that the upgrade can not take place. A possible reason is that the upgrade package that is running in the node is not in the upgrade window of this upgrade package. </description>
+ <description>Before an upgrade is started it was found that the upgrade cannot take place. A possible reason is that the upgrade package that is running in the node is not in the upgrade window of this upgrade package. </description>
<exceptionParameter name="message">
<dataType>
<string/>
@@ -1703,7 +1703,7 @@ Example:
<exception name="NoSuchAttributeException">
<description>Exception thrown when an MO attribute is requested to be accessed but the access
-method for the is not defined (the attribute can not be accessed)</description>
+method for the is not defined (the attribute cannot be accessed)</description>
</exception>
<exception name="MoCardinalityViolationException">
@@ -3125,7 +3125,7 @@ active = Synchronization is used in system clock generation.
<description>RefState can have the following values:
failed = synchronization reference is not capable to perform its required tasks.
degraded = capability of synchronization reference to perform its required tasks is degraded e.g. because of signal level degradation. This value is only applicable for traffic carrying (ET physical path termination) synchronization references. Note: attribute degradationIsFault controls whether synchronization reference degradation is interpreted as a synchronization reference fault or not.
-lossOfTracking = system clock regulation algorithm on TU board can not follow the 8kHz synchronization reference signal either because of the poor quality of the signal or because of a HW fault at TU board. If all synchronization references repeatedly end up to state lossOfTracking, fault is likely in TU HW.
+lossOfTracking = system clock regulation algorithm on TU board cannot follow the 8kHz synchronization reference signal either because of the poor quality of the signal or because of a HW fault at TU board. If all synchronization references repeatedly end up to state lossOfTracking, fault is likely in TU HW.
ok = synchronization reference is capable of performing its required tasks.
</description>
<enumMember name="failed">
@@ -11270,7 +11270,7 @@ Note! This action requires a transaction.</description>
The changing of the IP address with operation assignIpAddress might cause interruption of the communication if the network management tool is connected via the ethernet link.
-Note: The EthernetLink MO can not be deleted!
+Note: The EthernetLink MO cannot be deleted!
Note: The performance monitoring counters in the EthernetLink MO has a "Wrap-around time" of approximately 2 hours.
</description>
@@ -11532,8 +11532,8 @@ Note! This action requires a transaction.</description>
<description>This MO holds the IP routing table.
The IpRoutingTable MO is automatically created when the Ip MO is created.
-The IpRoutingTable MO can not be created manually.
-The IpRoutingTable MO can not be deleted.
+The IpRoutingTable MO cannot be created manually.
+The IpRoutingTable MO cannot be deleted.
</description>
<systemCreated/>
<attribute name="userLabel">
@@ -12967,7 +12967,7 @@ Note! When using fractional atm, timeslot 1 must be a part of the fraction.
Note! ETM1 does not support EPD and PPD
-Note! ETM1 does not have a proper buffer management. Thus fairness of UBR+ traffic can not be guaranteed and shaping on UBR+ traffic is not possible.
+Note! ETM1 does not have a proper buffer management. Thus fairness of UBR+ traffic cannot be guaranteed and shaping on UBR+ traffic is not possible.
Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 per port.
</description>
@@ -13371,7 +13371,7 @@ Struct element description :
-Date is in string format, max length is 40. Format for date is: weekday month date hour:min:seconds year.
-Status is in string format, max length is 40.
-Note! The identity can not be the same as name. Identity should contain the product identity.
+Note! The identity cannot be the same as name. Identity should contain the product identity.
</description>
@@ -13562,7 +13562,7 @@ Note! For comment and operatorName spaces (' ') are also allowed within the stri
This action does not require a transaction.
-Note! The configurationVersionName and identity can not be the same. The identity should be the product identity.
+Note! The configurationVersionName and identity cannot be the same. The identity should be the product identity.
</description>
<returnType>
<void/>
@@ -17367,7 +17367,7 @@ NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
<attribute name="mtp2ProfileItuId">
<description>Reference to a Mtp2ProfileItu MO.
-Note: The bitRate can not be changed.</description>
+Note: The bitRate cannot be changed.</description>
<mandatory/>
<noNotification/>
<dataType>
@@ -17566,7 +17566,7 @@ NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.</description>
<attribute name="mtp2ProfileAnsiId">
<description>Reference to a Mtp2ProfileAnsi MO.
-Note: The bitRate can not be changed.</description>
+Note: The bitRate cannot be changed.</description>
<mandatory/>
<noNotification/>
<dataType>
@@ -21777,7 +21777,7 @@ Each E1/DS1/J1 channel can suport up to 2 VP connections.
The ET-MC41 board support one biderectional F4/F5 PM flow per E1 channel.
-Note! The ETMC41 supports IMA. However the E1 ports being part of the same IMA group can not be selected randomly.
+Note! The ETMC41 supports IMA. However the E1 ports being part of the same IMA group cannot be selected randomly.
Note! The number of VCC TP+VPC TP with performance monitoring enabled (i.e. PM mode &lt;&gt; off) is restricted to 1 / port
@@ -21883,7 +21883,7 @@ NOTE: There is a restriction of a maximum of 32 Mtp2Tp's per MP.
<attribute name="mtp2ProfileChinaId">
<description>Reference to a Mtp2ProfileChina MO.
-Note: The bitRate can not be changed.</description>
+Note: The bitRate cannot be changed.</description>
<mandatory/>
<noNotification/>
<dataType>