diff options
-rw-r--r-- | erts/configure.in | 3 | ||||
-rw-r--r-- | erts/doc/src/erl.xml | 26 | ||||
-rw-r--r-- | erts/doc/src/erl_nif.xml | 4 | ||||
-rw-r--r-- | erts/doc/src/erlang.xml | 22 | ||||
-rw-r--r-- | erts/emulator/Makefile.in | 2 | ||||
-rw-r--r-- | erts/emulator/beam/atom.names | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 29 | ||||
-rw-r--r-- | erts/emulator/beam/erl_init.c | 16 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 31 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 2 | ||||
-rw-r--r-- | erts/emulator/drivers/common/inet_drv.c | 56 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 5 | ||||
-rw-r--r-- | erts/etc/common/erlexec.c | 1 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct.erl | 2 | ||||
-rw-r--r-- | lib/asn1/test/test_compile_options.erl | 2 | ||||
-rw-r--r-- | lib/crypto/c_src/Makefile.in | 24 | ||||
-rw-r--r-- | lib/crypto/c_src/crypto.c | 27 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 35 | ||||
-rw-r--r-- | lib/erl_interface/doc/src/ei_connect.xml | 6 | ||||
-rw-r--r-- | lib/erl_interface/src/connect/ei_connect.c | 8 | ||||
-rw-r--r-- | lib/erl_interface/src/epmd/epmd_port.c | 12 | ||||
-rw-r--r-- | lib/kernel/test/inet_SUITE.erl | 30 |
22 files changed, 281 insertions, 64 deletions
diff --git a/erts/configure.in b/erts/configure.in index 2b1aedc992..5747944bba 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -1788,6 +1788,9 @@ AC_CHECK_FUNCS([fdatasync]) dnl Find which C libraries are required to use fdatasync AC_SEARCH_LIBS(fdatasync, [rt]) +AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h) +AC_CHECK_FUNCS([getifaddrs]) + dnl ---------------------------------------------------------------------- dnl Checks for features/quirks in the system that affects Erlang. dnl ---------------------------------------------------------------------- diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index f477280a6f..e36d0adb0d 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -831,14 +831,28 @@ <p>For more information, see <seealso marker="erlang#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>.</p> </item> + <tag><marker id="+swt"><c>+swt very_low|low|medium|high|very_high</c></marker></tag> + <item> + <p>Set scheduler wakeup threshold. Default is <c>medium</c>. + The threshold determines when to wake up sleeping schedulers + when more work than can be handled by currently awake schedulers + exist. A low threshold will cause earlier wakeups, and a high + threshold will cause later wakeups. Early wakeups will + distribute work over multiple schedulers faster, but work will + more easily bounce between schedulers. + </p> + <p><em>NOTE:</em> This flag may be removed or changed at any time + without prior notice. + </p> + </item> + <tag><marker id="sched_thread_stack_size"><c><![CDATA[+sss size]]></c></marker></tag> + <item> + <p>Suggested stack size, in kilowords, for scheduler threads. + Valid range is 4-8192 kilowords. The default stack size + is OS dependent.</p> + </item> </taglist> </item> - <tag><marker id="sched_thread_stack_size"><c><![CDATA[+sss size]]></c></marker></tag> - <item> - <p>Suggested stack size, in kilowords, for scheduler threads. - Valid range is 4-8192 kilowords. The default stack size - is OS dependent.</p> - </item> <tag><marker id="+t"><c><![CDATA[+t size]]></c></marker></tag> <item> <p>Set the maximum number of atoms the VM can handle. Default is 1048576.</p> diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 8e4d8130f5..27887cbdf6 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2001</year><year>2009</year> + <year>2001</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1130,7 +1130,7 @@ typedef enum { </funcs> <section> <title>SEE ALSO</title> - <p><seealso marker="erlang#load_nif-2">load_nif(3)</seealso></p> + <p><seealso marker="erlang#load_nif-2">erlang:load_nif/2</seealso></p> </section> </cref> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 1eec45e0f3..ce7fde05d9 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -2034,12 +2034,14 @@ os_prompt%</pre> <v>Text = string()</v> </type> <desc> - <warning> - <p>This BIF is still an experimental feature. The interface - may be changed in any way in future releases.</p><p>In - R13B03 the return value on failure was + <note> + <p>In releases older than OTP R14B, NIF's where an + experimental feature. Versions of OTP older than R14B might + have different and possibly incompatible NIF semanticts and + interfaces. For example, in R13B03 the return value on + failure was <c>{error,Reason,Text}</c>.</p> - </warning> + </note> <p>Loads and links a dynamic library containing native implemented functions (NIFs) for a module. <c>Path</c> is a file path to the sharable object/dynamic library file minus @@ -5456,6 +5458,16 @@ true</pre> <seealso marker="#system_info_allocator_tuple">erlang:system_info({allocator, Alloc})</seealso>. </p> </item> + <tag><c>build_type</c></tag> + <item> + <p>Returns an atom describing the build type of the runtime + system. This is normally the atom <c>opt</c> for optimized. + Other possible return values are <c>debug</c>, <c>purify</c>, + <c>quantify</c>, <c>purecov</c>, <c>gcov</c>, <c>valgrind</c>, + <c>gprof</c>, and <c>lcnt</c>. Possible return values + may be added and/or removed at any time without prior notice. + </p> + </item> <tag><c>c_compiler_used</c></tag> <item> <p>Returns a two-tuple describing the C compiler used when diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index ed0d1b3fa6..903abe6f5c 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -74,7 +74,7 @@ else ifeq ($(TYPE),gcov) PURIFY = TYPEMARKER = .gcov -TYPE_FLAGS = @DEBUG_CFLAGS@ -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE= +TYPE_FLAGS = @DEBUG_CFLAGS@ -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE= ifneq ($(findstring solaris,$(TARGET)),solaris) LIBS += -lgcov endif diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 0815cdbc7f..327620772f 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -119,6 +119,7 @@ atom bsl atom bsr atom bsr_anycrlf atom bsr_unicode +atom build_type atom busy_dist_port atom busy_port atom call @@ -378,6 +379,7 @@ atom old_heap_size atom on_load atom open atom open_error +atom opt atom or atom ordered_set atom orelse diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index dace5b9297..40d8dc097c 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -1955,6 +1955,35 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1) : am_enabled); } #endif + } else if (BIF_ARG_1 == am_build_type) { +#if defined(DEBUG) + ERTS_DECL_AM(debug); + BIF_RET(AM_debug); +#elif defined(PURIFY) + ERTS_DECL_AM(purify); + BIF_RET(AM_purify); +#elif defined(QUANTIFY) + ERTS_DECL_AM(quantify); + BIF_RET(AM_quantify); +#elif defined(PURECOV) + ERTS_DECL_AM(purecov); + BIF_RET(AM_purecov); +#elif defined(ERTS_GCOV) + ERTS_DECL_AM(gcov); + BIF_RET(AM_gcov); +#elif defined(VALGRIND) + ERTS_DECL_AM(valgrind); + BIF_RET(AM_valgrind); +#elif defined(GPROF) + ERTS_DECL_AM(gprof); + BIF_RET(AM_gprof); +#elif defined(ERTS_ENABLE_LOCK_COUNT) + ERTS_DECL_AM(lcnt); + BIF_RET(AM_lcnt); +#else + BIF_RET(am_opt); +#endif + BIF_RET(res); } else if (BIF_ARG_1 == am_allocated_areas) { res = erts_allocated_areas(NULL, NULL, BIF_P); BIF_RET(res); diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 14bd10b42c..4ae656a3ad 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -512,6 +512,8 @@ void erts_usage(void) erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n"); erts_fprintf(stderr, "-sct cput set cpu topology,\n"); erts_fprintf(stderr, " see the erl(1) documentation for more info.\n"); + erts_fprintf(stderr, "-swt val set scheduler wakeup threshold, valid values are:\n"); + erts_fprintf(stderr, " very_low|low|medium|high|very_high.\n"); erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n"); erts_fprintf(stderr, " valid range is [%d-%d]\n", ERTS_SCHED_THREAD_MIN_STACK_SIZE, @@ -1176,10 +1178,20 @@ erl_start(int argc, char **argv) } else if (sys_strcmp("mrq", sub_param) == 0) use_multi_run_queue = 1; - else if (sys_strcmp("srq", sub_param) == 0) - use_multi_run_queue = 0; else if (sys_strcmp("nsp", sub_param) == 0) erts_use_sender_punish = 0; + else if (sys_strcmp("srq", sub_param) == 0) + use_multi_run_queue = 0; + else if (sys_strcmp("wt", sub_param) == 0) { + arg = get_arg(sub_param+2, argv[i+1], &i); + if (erts_sched_set_wakeup_limit(arg) != 0) { + erts_fprintf(stderr, "scheduler wakeup threshold: %s\n", + arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, + ("scheduler wakup threshold: %s\n", arg)); + } else if (has_prefix("ss", sub_param)) { /* suggested stack size (Kilo Words) for scheduler threads */ arg = get_arg(sub_param+2, argv[i+1], &i); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 2609457415..901167a315 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -54,7 +54,12 @@ (ERTS_SCHED_SYS_SLEEP_SPINCOUNT*ERTS_SCHED_TSE_SLEEP_SPINCOUNT_FACT) #define ERTS_SCHED_SUSPEND_SLEEP_SPINCOUNT 0 -#define ERTS_WAKEUP_OTHER_LIMIT (100*CONTEXT_REDS/2) +#define ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH (200*CONTEXT_REDS) +#define ERTS_WAKEUP_OTHER_LIMIT_HIGH (50*CONTEXT_REDS) +#define ERTS_WAKEUP_OTHER_LIMIT_MEDIUM (10*CONTEXT_REDS) +#define ERTS_WAKEUP_OTHER_LIMIT_LOW (CONTEXT_REDS) +#define ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW (CONTEXT_REDS/10) + #define ERTS_WAKEUP_OTHER_DEC 10 #define ERTS_WAKEUP_OTHER_FIXED_INC (CONTEXT_REDS/10) @@ -112,6 +117,8 @@ Uint erts_no_schedulers; Uint erts_max_processes = ERTS_DEFAULT_MAX_PROCESSES; Uint erts_process_tab_index_mask; +static int wakeup_other_limit; + #ifdef ERTS_SMP Uint erts_max_main_threads; #endif @@ -2373,7 +2380,27 @@ void erts_early_init_scheduling(void) { early_cpu_bind_init(); + wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM; +} + +int +erts_sched_set_wakeup_limit(char *str) +{ + if (sys_strcmp(str, "very_high") == 0) + wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_HIGH; + else if (sys_strcmp(str, "high") == 0) + wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_HIGH; + else if (sys_strcmp(str, "medium") == 0) + wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_MEDIUM; + else if (sys_strcmp(str, "low") == 0) + wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_LOW; + else if (sys_strcmp(str, "very_low") == 0) + wakeup_other_limit = ERTS_WAKEUP_OTHER_LIMIT_VERY_LOW; + else + return EINVAL; + return 0; } + void erts_init_scheduling(int mrq, int no_schedulers, int no_schedulers_online) @@ -7169,7 +7196,7 @@ Process *schedule(Process *p, int calls) if (rq->wakeup_other < 0) rq->wakeup_other = 0; } - else if (rq->wakeup_other < ERTS_WAKEUP_OTHER_LIMIT) + else if (rq->wakeup_other < wakeup_other_limit) rq->wakeup_other += rq->len*wo_reds + ERTS_WAKEUP_OTHER_FIXED_INC; else { if (erts_common_run_queue) { diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index e49710a7ed..4365e409e5 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -1038,6 +1038,8 @@ ErtsProcList *erts_proclist_create(Process *); void erts_proclist_destroy(ErtsProcList *); int erts_proclist_same(ErtsProcList *, Process *); +int erts_sched_set_wakeup_limit(char *str); + #ifdef DEBUG void erts_dbg_multi_scheduling_return_trap(Process *, Eterm); #endif diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 79e58beb40..3f761eeb19 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -48,6 +48,12 @@ #include <sys/uio.h> #endif +#ifdef HAVE_NET_IF_DL_H +#include <net/if_dl.h> +#endif +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif /* All platforms fail on malloc errors. */ #define FATAL_MALLOC @@ -3905,7 +3911,7 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, INTERFACE_INFO* ifp; long namaddr; - if ((len == 0) || ((namlen = buf[0]) > len)) + if ((len == 0) || ((namlen = get_int8(buf)) > len)) goto error; if (parse_addr(buf+1, namlen, &namaddr) < 0) goto error; @@ -4089,6 +4095,10 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) } +/* FIXME: temporary hack */ +#ifndef IFHWADDRLEN +#define IFHWADDRLEN 6 +#endif static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, char** rbuf, int rsize) @@ -4099,11 +4109,11 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, struct ifreq ifreq; int namlen; - if ((len == 0) || ((namlen = buf[0]) > len)) + if ((len == 0) || ((namlen = get_int8(buf)) > len)) goto error; sys_memset(ifreq.ifr_name, '\0', IFNAMSIZ); sys_memcpy(ifreq.ifr_name, buf+1, - (namlen > IFNAMSIZ) ? IFNAMSIZ : namlen); + (namlen >= IFNAMSIZ) ? IFNAMSIZ-1 : namlen); buf += (namlen+1); len -= (namlen+1); sptr = sbuf; @@ -4128,6 +4138,32 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, /* raw memcpy (fix include autoconf later) */ sys_memcpy(sptr, (char*)(&ifreq.ifr_hwaddr.sa_data), IFHWADDRLEN); sptr += IFHWADDRLEN; +#elif defined(HAVE_GETIFADDRS) + struct ifaddrs *ifa, *ifp; + int found = 0; + + if (getifaddrs(&ifa) == -1) + goto error; + + for (ifp = ifa; ifp; ifp = ifp->ifa_next) { + if ((ifp->ifa_addr->sa_family == AF_LINK) && + (sys_strcmp(ifp->ifa_name, ifreq.ifr_name) == 0)) { + found = 1; + break; + } + } + + if (found == 0) { + freeifaddrs(ifa); + break; + } + + buf_check(sptr, s_end, 1+IFHWADDRLEN); + *sptr++ = INET_IFOPT_HWADDR; + sys_memcpy(sptr, ((struct sockaddr_dl *)ifp->ifa_addr)->sdl_data + + ((struct sockaddr_dl *)ifp->ifa_addr)->sdl_nlen, IFHWADDRLEN); + freeifaddrs(ifa); + sptr += IFHWADDRLEN; #endif break; } @@ -4240,10 +4276,6 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, return ctl_error(EINVAL, rbuf, rsize); } -/* FIXME: temporary hack */ -#ifndef IFHWADDRLEN -#define IFHWADDRLEN 6 -#endif static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, char** rbuf, int rsize) @@ -4252,11 +4284,11 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, int namlen; char* b_end = buf + len; - if ((len == 0) || ((namlen = buf[0]) > len)) + if ((len == 0) || ((namlen = get_int8(buf)) > len)) goto error; sys_memset(ifreq.ifr_name, '\0', IFNAMSIZ); sys_memcpy(ifreq.ifr_name, buf+1, - (namlen > IFNAMSIZ) ? IFNAMSIZ : namlen); + (namlen >= IFNAMSIZ) ? IFNAMSIZ-1 : namlen); buf += (namlen+1); len -= (namlen+1); @@ -6851,13 +6883,13 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, if (len < 2) return ctl_error(EINVAL, rbuf, rsize); - n = buf[0]; buf++; len--; + n = get_int8(buf); buf++; len--; if (n >= len) /* the = sign makes the test inklude next length byte */ return ctl_error(EINVAL, rbuf, rsize); memcpy(namebuf, buf, n); namebuf[n] = '\0'; len -= n; buf += n; - n = buf[0]; buf++; len--; + n = get_int8(buf); buf++; len--; if (n > len) return ctl_error(EINVAL, rbuf, rsize); memcpy(protobuf, buf, n); @@ -6880,7 +6912,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, port = get_int16(buf); port = sock_htons(port); buf += 2; - n = buf[0]; buf++; len -= 3; + n = get_int8(buf); buf++; len -= 3; if (n > len) return ctl_error(EINVAL, rbuf, rsize); memcpy(protobuf, buf, n); diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 5384a32f21..8489124966 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -1029,8 +1029,11 @@ static ERL_NIF_TERM make_term_list0(struct make_term_info* mti, int n) static ERL_NIF_TERM make_term_resource(struct make_term_info* mti, int n) { void* resource = enif_alloc_resource(mti->resource_type, 10); + ERL_NIF_TERM term; fill(resource, 10, n); - return enif_make_resource(mti->dst_env, resource); + term = enif_make_resource(mti->dst_env, resource); + enif_release_resource(resource); + return term; } static ERL_NIF_TERM make_term_new_binary(struct make_term_info* mti, int n) { diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 76ce0a7e3c..c1fc2aebee 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -120,6 +120,7 @@ static char *plusM_other_switches[] = { static char *pluss_val_switches[] = { "bt", "ct", + "wt", "ss", NULL }; diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index ae681a4a78..968468cb7f 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1674,7 +1674,7 @@ create_pdec_inc_command(ModName, % [concat_sequential(lists:reverse(Comms), % [LastComm,CompAcc])|Acc] case lists:reverse(TagCommand) of - [Atom|Comms]�when is_atom(Atom) -> + [Atom|Comms] when is_atom(Atom) -> [concat_sequential(lists:reverse(Comms), [Atom,CompAcc])|Acc]; [[Command2,Tag2]|Comms] -> diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl index 83f38c5e6d..5e027cdedb 100644 --- a/lib/asn1/test/test_compile_options.erl +++ b/lib/asn1/test/test_compile_options.erl @@ -132,7 +132,7 @@ verbose(Config) when is_list(Config) -> ?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj,verbose]), ?line test_server:capture_stop(), ?line [Line0|_] = test_server:capture_get(), - ?line lists:prefix("Erlang ASN.1 version", Line0), + ?line true = lists:prefix("Erlang ASN.1 version", Line0), %% Test non-verbose compile ?line test_server:capture_start(), diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in index e728db18eb..040adcfd09 100644 --- a/lib/crypto/c_src/Makefile.in +++ b/lib/crypto/c_src/Makefile.in @@ -68,13 +68,13 @@ RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN) # ---------------------------------------------------- # Misc Macros # ---------------------------------------------------- -OBJS = $(OBJDIR)/crypto.o +OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o NIF_MAKEFILE = $(PRIVDIR)/Makefile ifeq ($(findstring win32,$(TARGET)), win32) -NIF_LIB = $(LIBDIR)/crypto.dll +NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll else -NIF_LIB = $(LIBDIR)/crypto.so +NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so endif ifeq ($(HOST_OS),) @@ -102,20 +102,30 @@ $(OBJDIR): $(LIBDIR): -@mkdir -p $(LIBDIR) -$(OBJDIR)/%.o: %.c +$(OBJDIR)/%$(TYPEMARKER).o: %.c $(INSTALL_DIR) $(OBJDIR) $(CC) -c -o $@ $(ALL_CFLAGS) $< -$(LIBDIR)/crypto.so: $(OBJS) +$(LIBDIR)/crypto$(TYPEMARKER).so: $(OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CRYPTO_LINK_LIB) -$(LIBDIR)/crypto.dll: $(OBJS) +$(LIBDIR)/crypto$(TYPEMARKER).dll: $(OBJS) $(INSTALL_DIR) $(LIBDIR) $(LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(OBJS) -llibeay32 clean: - rm -f $(NIF_LIB) $(OBJS) +ifeq ($(findstring win32,$(TARGET)), win32) + rm -f $(LIBDIR)/crypto.dll + rm -f $(LIBDIR)/crypto.debug.dll +else + rm -f $(LIBDIR)/crypto.so + rm -f $(LIBDIR)/crypto.debug.so + rm -f $(LIBDIR)/crypto.valgrind.so +endif + rm -f $(OBJDIR)/crypto.o + rm -f $(OBJDIR)/crypto.debug.o + rm -f $(OBJDIR)/crypto.valgrind.o rm -f core *~ docs: diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 8823bba3b6..85614a84c2 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -64,8 +64,8 @@ # define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size) \ ((void) ((VALGRIND_CHECK_MEM_IS_DEFINED(ptr,size) == 0) ? 1 : \ - (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%d) failed at %s:%d\r\n",\ - (ptr),(size), __FILE__, __LINE__), abort(), 0))) + (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%ld) failed at %s:%d\r\n",\ + (ptr),(long)(size), __FILE__, __LINE__), abort(), 0))) #else # define ERL_VALGRIND_MAKE_MEM_DEFINED(ptr,size) # define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size) @@ -706,12 +706,13 @@ static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Lo,Hi) */ - BIGNUM *bn_from, *bn_to, *bn_rand; + BIGNUM *bn_from = NULL, *bn_to, *bn_rand; unsigned char* data; unsigned dlen; ERL_NIF_TERM ret; if (!get_bn_from_mpint(env, argv[0], &bn_from) || !get_bn_from_mpint(env, argv[1], &bn_rand)) { + if (bn_from) BN_free(bn_from); return enif_make_badarg(env); } @@ -770,7 +771,7 @@ static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin) static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (DigestType,Data,Signature,Key=[P, Q, G, Y]) */ ErlNifBinary data_bin, sign_bin; - BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_y; + BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL; unsigned char hmacbuf[SHA_DIGEST_LENGTH]; ERL_NIF_TERM head, tail; DSA *dsa; @@ -786,6 +787,11 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv || !enif_get_list_cell(env, tail, &head, &tail) || !get_bn_from_mpint(env, head, &dsa_y) || !enif_is_empty_list(env,tail)) { + badarg: + if (dsa_p) BN_free(dsa_p); + if (dsa_q) BN_free(dsa_q); + if (dsa_g) BN_free(dsa_g); + if (dsa_y) BN_free(dsa_y); return enif_make_badarg(env); } if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) { @@ -796,7 +802,7 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH); } else { - return enif_make_badarg(env); + goto badarg; } dsa = DSA_new(); @@ -1119,7 +1125,7 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER enif_alloc_binary(RSA_size(rsa), &ret_bin); if (argv[3] == atom_true) { - ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size); i = RSA_public_encrypt(data_bin.size, data_bin.data, ret_bin.data, rsa, padding); if (i > 0) { @@ -1139,6 +1145,7 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER return enif_make_binary(env,&ret_bin); } else { + enif_release_binary(&ret_bin); return atom_error; } } @@ -1167,7 +1174,7 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE enif_alloc_binary(RSA_size(rsa), &ret_bin); if (argv[3] == atom_true) { - ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size); i = RSA_private_encrypt(data_bin.size, data_bin.data, ret_bin.data, rsa, padding); if (i > 0) { @@ -1187,6 +1194,7 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE return enif_make_binary(env,&ret_bin); } else { + enif_release_binary(&ret_bin); return atom_error; } } @@ -1266,7 +1274,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ || !enif_get_list_cell(env, tail, &head, &tail) || !get_bn_from_mpint(env, head, &dh_params->g) || !enif_is_empty_list(env, tail)) { - + DH_free(dh_params); return enif_make_badarg(env); } @@ -1293,7 +1301,7 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */ DH* dh_params = DH_new(); - BIGNUM* pubkey; + BIGNUM* pubkey = NULL; int i; ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; @@ -1321,6 +1329,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ret = atom_error; } } + if (pubkey) BN_free(pubkey); DH_free(dh_params); return ret; } diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 19fa495b7d..71fd91cafd 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -93,22 +93,42 @@ -define(CRYPTO_NIF_VSN,101). on_load() -> - LibName = "crypto", + LibBaseName = "crypto", PrivDir = code:priv_dir(crypto), - Lib1 = filename:join([PrivDir, "lib", LibName]), - Status = case erlang:load_nif(Lib1, ?CRYPTO_NIF_VSN) of + LibName = case erlang:system_info(build_type) of + opt -> + LibBaseName; + Type -> + LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type), + case (filelib:wildcard( + filename:join( + [PrivDir, + "lib", + LibTypeName ++ "*"])) /= []) orelse + (filelib:wildcard( + filename:join( + [PrivDir, + "lib", + erlang:system_info(system_architecture), + LibTypeName ++ "*"])) /= []) of + true -> LibTypeName; + false -> LibBaseName + end + end, + Lib = filename:join([PrivDir, "lib", LibName]), + Status = case erlang:load_nif(Lib, ?CRYPTO_NIF_VSN) of ok -> ok; {error, {load_failed, _}}=Error1 -> - LibDir2 = + ArchLibDir = filename:join([PrivDir, "lib", erlang:system_info(system_architecture)]), Candidate = - filelib:wildcard(filename:join([LibDir2,LibName ++ "*" ])), + filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])), case Candidate of [] -> Error1; _ -> - Lib2 = filename:join([LibDir2, LibName]), - erlang:load_nif(Lib2, ?CRYPTO_NIF_VSN) + ArchLib = filename:join([ArchLibDir, LibName]), + erlang:load_nif(ArchLib, ?CRYPTO_NIF_VSN) end; Error1 -> Error1 end, @@ -119,7 +139,6 @@ on_load() -> "OpenSSL might not be installed on this system.~n",[E,Str]), Status end. - nif_stub_error(Line) -> erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml index 927395d1bf..36dfb149cc 100644 --- a/lib/erl_interface/doc/src/ei_connect.xml +++ b/lib/erl_interface/doc/src/ei_connect.xml @@ -116,7 +116,7 @@ int n = 0; struct in_addr addr; ei_cnode ec; -addr = inet_addr("150.236.14.75"); +addr.s_addr = inet_addr("150.236.14.75"); if (ei_connect_xinit(&ec, "chivas", "madonna", @@ -132,7 +132,7 @@ if (ei_connect_xinit(&ec, </p> <code type="none"><![CDATA[ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) { - fprintf("ERROR when initializing: %d",erl_errno); + fprintf(stderr,"ERROR when initializing: %d",erl_errno); exit(-1); } ]]></code> @@ -177,7 +177,7 @@ int fd = ei_connect(&ec, NODE); /*** Variant 2 ***/ struct in_addr addr; -addr = inet_addr(IP_ADDR); +addr.s_addr = inet_addr(IP_ADDR); fd = ei_xconnect(&ec, &addr, ALIVE); ]]></code> </desc> diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c index b1b79aa0e5..e191f3fbf0 100644 --- a/lib/erl_interface/src/connect/ei_connect.c +++ b/lib/erl_interface/src/connect/ei_connect.c @@ -502,10 +502,14 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name, return ERL_ERROR; } - if (this_node_name == NULL) + if (this_node_name == NULL) { sprintf(thisalivename, "c%d", (int) getpid()); - else + } else if (strlen(this_node_name) >= sizeof(thisalivename)) { + EI_TRACE_ERR0("ei_connect_init","ERROR: this_node_name too long"); + return ERL_ERROR; + } else { strcpy(thisalivename, this_node_name); + } if ((hp = ei_gethostbyname(thishostname)) == 0) { /* Looking up IP given hostname fails. We must be on a standalone diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c index 663b38d2d4..cf6122fafa 100644 --- a/lib/erl_interface/src/epmd/epmd_port.c +++ b/lib/erl_interface/src/epmd/epmd_port.c @@ -106,6 +106,12 @@ static int ei_epmd_r3_port (struct in_addr *addr, const char *alive, char ntoabuf[32]; #endif + if (len > sizeof(buf) - 3) + { + erl_errno = ERANGE; + return -1; + } + put16be(s,len); put8(s,EI_EPMD_PORT_REQ); strcpy(s,alive); @@ -164,6 +170,12 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive, #if defined(VXWORKS) char ntoabuf[32]; #endif + + if (len > sizeof(buf) - 3) + { + erl_errno = ERANGE; + return -1; + } put16be(s,len); put8(s,EI_EPMD_PORT2_REQ); diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index eb8f918491..f4f27933a5 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -26,7 +26,8 @@ t_gethostbyaddr_v6/1, t_getaddr_v6/1, t_gethostbyname_v6/1, ipv4_to_ipv6/1, host_and_addr/1, parse/1, t_gethostnative/1, gethostnative_parallell/1, cname_loop/1, - gethostnative_soft_restart/1,gethostnative_debug_level/1,getif/1]). + gethostnative_soft_restart/1,gethostnative_debug_level/1,getif/1, + getif_ifr_name_overflow/1,getservbyname_overflow/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0]). @@ -39,7 +40,7 @@ all(suite) -> ipv4_to_ipv6, host_and_addr, parse,t_gethostnative, gethostnative_parallell, cname_loop, gethostnative_debug_level,gethostnative_soft_restart, - getif]. + getif,getif_ifr_name_overflow,getservbyname_overflow]. init_per_testcase(_Func, Config) -> Dog = test_server:timetrap(test_server:seconds(60)), @@ -876,6 +877,17 @@ getif(Config) when is_list(Config) -> ?line {ok,Address} = inet:getaddr(Hostname, inet), ?line {ok,Loopback} = inet:getaddr("localhost", inet), ?line {ok,Interfaces} = inet:getiflist(), + ?line HWAs = + lists:sort( + lists:foldl( + fun (I, Acc) -> + case inet:ifget(I, [hwaddr]) of + {ok,[{hwaddr,A}]} -> [A|Acc]; + {ok,[]} -> Acc + end + end, [], Interfaces)), + ?line io:format("HWAs = ~p~n", [HWAs]), + ?line length(HWAs) > 0 orelse ?t:fail(no_HWAs), ?line Addresses = lists:sort( lists:foldl( @@ -891,6 +903,20 @@ getif(Config) when is_list(Config) -> ?line true = ip_member(Loopback, Addresses), ?line ok. +getif_ifr_name_overflow(doc) -> + "Test long interface names do not overrun buffer"; +getif_ifr_name_overflow(Config) when is_list(Config) -> + %% emulator should not crash + ?line {ok,[]} = inet:ifget(lists:duplicate(128, "x"), [addr]), + ok. + +getservbyname_overflow(doc) -> + "Test long service names do not overrun buffer"; +getservbyname_overflow(Config) when is_list(Config) -> + %% emulator should not crash + ?line {error,einval} = inet:getservbyname(list_to_atom(lists:flatten(lists:duplicate(128, "x"))), tcp), + ok. + %% Works just like lists:member/2, except that any {127,_,_,_} tuple %% matches any other {127,_,_,_}. We do this to handle Linux systems %% that use (for instance) 127.0.1.1 as the IP address for the hostname. |