aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/doc/src/asn1ct.xml7
-rw-r--r--lib/asn1/src/asn1ct.erl37
-rw-r--r--lib/asn1/src/asn1ct_gen.erl26
-rw-r--r--lib/asn1/src/asn1ct_gen_ber.erl12
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl12
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl12
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl12
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src3
-rw-r--r--lib/asn1/test/test_compile_options.erl21
-rw-r--r--lib/dialyzer/doc/manual.txt2
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml8
-rw-r--r--lib/hipe/arm/hipe_arm_pp.erl17
-rw-r--r--lib/hipe/cerl/erl_types.erl2
-rw-r--r--lib/public_key/src/pubkey_pem.erl12
-rw-r--r--lib/ssl/doc/src/new_ssl.xml7
-rw-r--r--lib/ssl/src/ssl.erl26
-rw-r--r--lib/ssl/src/ssl_connection.erl203
-rw-r--r--lib/ssl/src/ssl_handshake.erl8
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl115
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl174
-rw-r--r--lib/ssl/test/ssl_test_lib.erl40
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl2
-rw-r--r--lib/ssl/vsn.mk6
-rw-r--r--lib/stdlib/src/epp.erl49
-rw-r--r--lib/stdlib/test/epp_SUITE.erl50
-rw-r--r--lib/xmerl/doc/src/notes.xml24
-rw-r--r--lib/xmerl/vsn.mk9
27 files changed, 634 insertions, 262 deletions
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index 8a0ae52c39..265f8735c2 100644
--- a/lib/asn1/doc/src/asn1ct.xml
+++ b/lib/asn1/doc/src/asn1ct.xml
@@ -53,7 +53,7 @@
<v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string |
noobj | {n2n,EnumTypeName} |{outdir,Dir} | {i,IncludeDir} | optimize |
driver | asn1config | undec_rest | {inline,OutputName} | inline |
- {macro_name_prefix, Prefix} | {record_name_prefix, Prefix}</v>
+ {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose</v>
<v>OldOption = ber | per</v>
<v>Reason = term()</v>
<v>Prefix = string()</v>
@@ -284,6 +284,11 @@ Binary = binary()
<c>Prefix</c>. This is useful when multiple protocols that contains
records with identical names are included in a single module.</p>
</item>
+ <tag><c>verbose</c></tag>
+ <item>
+ <p>Causes more verbose information from the compiler
+ describing what it is doing.</p>
+ </item>
</taglist>
<p>Any additional option that is applied will be passed to
the final step when the generated .erl file is compiled.
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index e6fd3663dd..1859428c49 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -39,7 +39,7 @@
add_tobe_refed_func/1,add_generated_refed_func/1,
maybe_rename_function/3,latest_sindex/0,current_sindex/0,
set_current_sindex/1,next_sindex/0,maybe_saved_sindex/2,
- parse_and_save/2]).
+ parse_and_save/2,report_verbose/3]).
-include("asn1_records.hrl").
-include_lib("stdlib/include/erl_compile.hrl").
@@ -103,8 +103,8 @@ compile(File,Options) when is_list(Options) ->
compile1(File,Options) when is_list(Options) ->
- io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File]),
- io:format("Compiler Options: ~p~n",[Options]),
+ report_verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File],Options),
+ report_verbose("Compiler Options: ~p~n",[Options],Options),
Ext = filename:extension(File),
Base = filename:basename(File,Ext),
OutFile = outfile(Base,"",Options),
@@ -152,7 +152,7 @@ inline(true,Name,Module,Options) ->
IgorName = filename:rootname(filename:basename(Name)),
% io:format("*****~nName: ~p~nModules: ~p~nIgorOptions: ~p~n*****~n",
% [IgorName,Modules++RTmodule,IgorOptions]),
- io:format("Inlining modules: ~p in ~p~n",[[Module]++RTmodule,IgorName]),
+ report_verbose("Inlining modules: ~p in ~p~n",[[Module]++RTmodule,IgorName],Options),
case catch igor:merge(IgorName,[Module]++RTmodule,[{preprocess,true},{stubs,false},{backups,false}]++IgorOptions) of
{'EXIT',{undef,Reason}} -> %% module igor first in R10B
io:format("Module igor in syntax_tools must be available:~n~p~n",
@@ -173,8 +173,8 @@ inline(_,_,_,_) ->
compile_set(SetBase,Files,Options)
when is_list(hd(Files)),is_list(Options) ->
%% case when there are several input files in a list
- io:format("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files]),
- io:format("Compiler Options: ~p~n",[Options]),
+ report_verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,Files],Options),
+ report_verbose("Compiler Options: ~p~n",[Options],Options),
OutFile = outfile(SetBase,"",Options),
DbFile = outfile(SetBase,"asn1db",Options),
Includes = [I || {i,I} <- Options],
@@ -802,7 +802,7 @@ check({true,M},File,OutFile,Includes,EncodingRule,DbFile,Options,InputMods) ->
NewM = Module#module{typeorval=NewTypeOrVal},
asn1_db:dbput(NewM#module.name,'MODULE',NewM),
asn1_db:dbsave(DbFile,M#module.name),
- io:format("--~p--~n",[{generated,DbFile}]),
+ report_verbose("--~p--~n",[{generated,DbFile}],Options),
{true,{M,NewM,GenTypeOrVal}}
end
end;
@@ -833,7 +833,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) ->
Result =
case (catch asn1ct_gen:pgen(OutFile,EncodingRule,
- M#module.name,GenTOrV)) of
+ M#module.name,GenTOrV,Options)) of
{'EXIT',Reason2} ->
io:format("ERROR: ~p~n",[Reason2]),
{error,Reason2};
@@ -2518,3 +2518,14 @@ type_check(#'Externaltypereference'{}) ->
lists:concat(["_",I]);
make_suffix(_) ->
"".
+
+report_verbose(Format, Args, S) ->
+ case is_verbose(S) of
+ true ->
+ io:format(Format, Args);
+ false ->
+ ok
+ end.
+
+is_verbose(S) ->
+ lists:member(verbose, S).
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index b9f6c46b53..eab5fb4a2a 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -22,7 +22,7 @@
-include("asn1_records.hrl").
-export([pgen_exports/3,
- pgen_hrl/4,
+ pgen_hrl/5,
gen_head/3,
demit/1,
emit/1,
@@ -41,28 +41,29 @@
rt2ct_suffix/0,
index2suffix/1,
get_record_name_prefix/0]).
--export([pgen/4,
- pgen_module/5,
+-export([pgen/5,
+ pgen_module/6,
mk_var/1,
un_hyphen_var/1]).
-export([gen_encode_constructed/4,
gen_decode_constructed/4]).
-%% pgen(Erules, Module, TypeOrVal)
+%% pgen(Outfile, Erules, Module, TypeOrVal, Options)
%% Generate Erlang module (.erl) and (.hrl) file corresponding to an ASN.1 module
%% .hrl file is only generated if necessary
%% Erules = per | ber | ber_bin | per_bin
%% Module = atom()
%% TypeOrVal = {TypeList,ValueList}
%% TypeList = ValueList = [atom()]
+%% Options = [Options] from asn1ct:compile()
-pgen(OutFile,Erules,Module,TypeOrVal) ->
- pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+pgen(OutFile,Erules,Module,TypeOrVal,Options) ->
+ pgen_module(OutFile,Erules,Module,TypeOrVal,Options,true).
pgen_module(OutFile,Erules,Module,
TypeOrVal = {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets},
- Indent) ->
+ Options,Indent) ->
N2nConvEnums = [CName|| {n2n,CName} <- get(encoding_options)],
case N2nConvEnums -- Types of
[] ->
@@ -72,7 +73,7 @@ pgen_module(OutFile,Erules,Module,
UnmatchedTypes})
end,
put(outfile,OutFile),
- HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Indent),
+ HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent),
asn1ct_name:start(),
ErlFile = lists:concat([OutFile,".erl"]),
Fid = fopen(ErlFile,[write]),
@@ -86,7 +87,7 @@ pgen_module(OutFile,Erules,Module,
% gen_vars(asn1_db:mod_to_vars(Module)),
% gen_tag_table(AllTypes),
file:close(Fid),
- io:format("--~p--~n",[{generated,ErlFile}]).
+ asn1ct:report_verbose("--~p--~n",[{generated,ErlFile}],Options).
pgen_typeorval(Erules,Module,N2nConvEnums,{Types,Values,_Ptypes,_Classes,Objects,ObjectSets}) ->
@@ -1310,7 +1311,7 @@ fopen(F, ModeList) ->
exit({error,Reason})
end.
-pgen_hrl(Erules,Module,TypeOrVal,_Indent) ->
+pgen_hrl(Erules,Module,TypeOrVal,Options,_Indent) ->
put(currmod,Module),
{Types,Values,Ptypes,_,_,_} = TypeOrVal,
Ret =
@@ -1334,8 +1335,9 @@ pgen_hrl(Erules,Module,TypeOrVal,_Indent) ->
Y ->
Fid = get(gen_file_out),
file:close(Fid),
- io:format("--~p--~n",
- [{generated,lists:concat([get(outfile),".hrl"])}]),
+ asn1ct:report_verbose("--~p--~n",
+ [{generated,lists:concat([get(outfile),".hrl"])}],
+ Options),
Y
end.
diff --git a/lib/asn1/src/asn1ct_gen_ber.erl b/lib/asn1/src/asn1ct_gen_ber.erl
index 7c432f29c3..d70586c75c 100644
--- a/lib/asn1/src/asn1ct_gen_ber.erl
+++ b/lib/asn1/src/asn1ct_gen_ber.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -67,7 +67,7 @@
%% TypeList = ValueList = [atom()]
pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
%%===============================================================================
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index b7ac0f407c..a146e92d64 100644
--- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
+++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -67,7 +67,7 @@
%% TypeList = ValueList = [atom()]
pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
%%===============================================================================
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 06d2489748..23fb392d60 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -43,7 +43,7 @@
%% TypeList = ValueList = [atom()]
pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
%% Generate ENCODING ******************************
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 56f895828a..e1feb42a59 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -43,7 +43,7 @@
%% TypeList = ValueList = [atom()]
pgen(OutFile,Erules,Module,TypeOrVal) ->
- asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,true).
+ asn1ct_gen:pgen_module(OutFile,Erules,Module,TypeOrVal,[],true).
%% Generate ENCODING ******************************
diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src
index 9d3f03fc4c..ca73d259af 100644
--- a/lib/asn1/test/asn1_SUITE.erl.src
+++ b/lib/asn1/test/asn1_SUITE.erl.src
@@ -2240,7 +2240,8 @@ test_compile_options(Config) ->
?line ok = test_compile_options:wrong_path(Config),
?line ok = test_compile_options:path(Config),
?line ok = test_compile_options:noobj(Config),
- ?line ok = test_compile_options:record_name_prefix(Config)
+ ?line ok = test_compile_options:record_name_prefix(Config),
+ ?line ok = test_compile_options:verbose(Config)
end.
testDoubleEllipses(suite) -> [];
testDoubleEllipses(Config) ->
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index d51b2a6c4a..83f38c5e6d 100644
--- a/lib/asn1/test/test_compile_options.erl
+++ b/lib/asn1/test/test_compile_options.erl
@@ -24,7 +24,7 @@
-export([wrong_path/1,comp/2,path/1,ticket_6143/1,noobj/1,
- record_name_prefix/1]).
+ record_name_prefix/1,verbose/1]).
%% OTP-5689
wrong_path(Config) ->
@@ -122,6 +122,25 @@ noobj(Config) ->
file:delete(filename:join([OutDir,'p_record.erl'])),
file:delete(filename:join([OutDir,'p_record.beam'])).
+verbose(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir,Config),
+ OutDir = ?config(priv_dir,Config),
+ Asn1File = filename:join([DataDir,"Comment.asn"]),
+
+ %% Test verbose compile
+ ?line test_server:capture_start(),
+ ?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),
+
+ %% Test non-verbose compile
+ ?line test_server:capture_start(),
+ ?line ok = asn1ct:compile(Asn1File, [{i,DataDir},{outdir,OutDir},noobj]),
+ ?line test_server:capture_stop(),
+ ?line [] = test_server:capture_get(),
+ ok.
+
outfiles_check(OutDir) ->
outfiles_check(OutDir,outfiles1()).
diff --git a/lib/dialyzer/doc/manual.txt b/lib/dialyzer/doc/manual.txt
index dac61b74b1..470ddd6c73 100644
--- a/lib/dialyzer/doc/manual.txt
+++ b/lib/dialyzer/doc/manual.txt
@@ -297,7 +297,7 @@ Option :: {files, [Filename :: string()]}
| {include_dirs, [DirName :: string()]}
| {output_file, FileName :: string()}
| {output_plt, FileName :: string()}
- | {analysis_type, 'success_typings' | 'plt_add' |
+ | {analysis_type, 'succ_typings' | 'plt_add' |
'plt_build' | 'plt_check' | 'plt_remove'}
| {warnings, [WarnOpts]}
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 7f983a2c0d..1ec2ce830a 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2009</year>
+ <year>2006</year><year>2010</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -13,12 +13,12 @@
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
-
+
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
-
+
</legalnotice>
<title>dialyzer</title>
@@ -206,7 +206,7 @@ Option : {files, [Filename : string()]}
| {include_dirs, [DirName : string()]}
| {output_file, FileName : string()}
| {output_plt, FileName :: string()}
- | {analysis_type, 'success_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'}
+ | {analysis_type, 'succ_typings' | 'plt_add' | 'plt_build' | 'plt_check' | 'plt_remove'}
| {warnings, [WarnOpts]}
| {get_warnings, bool()}
diff --git a/lib/hipe/arm/hipe_arm_pp.erl b/lib/hipe/arm/hipe_arm_pp.erl
index 7ce8421994..c4dde31188 100644
--- a/lib/hipe/arm/hipe_arm_pp.erl
+++ b/lib/hipe/arm/hipe_arm_pp.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 2 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -246,6 +246,11 @@ stop_suffix(StOp) ->
'strb' -> "b"
end.
+imm8m_decode(Value, 0) ->
+ Value;
+imm8m_decode(Value, Rot) ->
+ (Value bsr (2 * Rot)) bor (Value bsl (2 * (16 - Rot))).
+
pp_temp(Dev, Temp=#arm_temp{reg=Reg, type=Type}) ->
case hipe_arm:temp_is_precoloured(Temp) of
true ->
@@ -292,7 +297,7 @@ pp_am1(Dev, Am1) ->
io:format(Dev, "#~w", [Imm5])
end;
{Imm8,Imm4} ->
- io:format(Dev, "#~w, 2*~w", [Imm8,Imm4])
+ io:format(Dev, "#~s", [to_hex(imm8m_decode(Imm8, Imm4))])
end.
pp_am2(Dev, #am2{src=Src,sign=Sign,offset=Am2Offset}) ->
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index b4d80d359a..f3b91b3953 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -322,7 +322,7 @@
-define(nil, #c{tag=?nil_tag}).
-define(nonempty_list(Types, Term),?list(Types, Term, ?nonempty_qual)).
-define(number(Set, Qualifier), #c{tag=?number_tag, elements=Set,
- qualifier=Qualifier}.
+ qualifier=Qualifier}).
-define(opaque(Optypes), #c{tag=?opaque_tag, elements=Optypes}).
-define(product(Types), #c{tag=?product_tag, elements=Types}).
-define(remote(RemTypes), #c{tag=?remote_tag, elements=RemTypes}).
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index abd46fa00e..9fc17b6f73 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -155,7 +155,7 @@ unhex(S) ->
unhex(S, []).
unhex("", Acc) ->
- lists:reverse(Acc);
+ list_to_binary(lists:reverse(Acc));
unhex([D1, D2 | Rest], Acc) ->
unhex(Rest, [erlang:list_to_integer([D1, D2], 16) | Acc]).
diff --git a/lib/ssl/doc/src/new_ssl.xml b/lib/ssl/doc/src/new_ssl.xml
index a83c2d1383..08868a1b3c 100644
--- a/lib/ssl/doc/src/new_ssl.xml
+++ b/lib/ssl/doc/src/new_ssl.xml
@@ -495,12 +495,15 @@ end
</func>
<func>
- <name>renegotiate(Socket) -> ok</name>
+ <name>renegotiate(Socket) -> ok | {error, Reason}</name>
<fsummary> Initiates a new handshake.</fsummary>
<type>
<v>Socket = sslsocket()</v>
</type>
- <desc><p>Initiates a new handshake.</p>
+ <desc><p>Initiates a new handshake. A notable return value is
+ <c>{error, renegotiation_rejected}</c> indicating that the peer
+ refused to go through with the renegotiation but the connection
+ is still active using the previously negotiated session.</p>
</desc>
</func>
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 965e40a109..da5f750762 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -154,17 +154,21 @@ transport_accept(#sslsocket{pid = {ListenSocket, #config{cb=CbInfo, ssl=SslOpts}
EmOptions = emulated_options(),
{ok, InetValues} = inet:getopts(ListenSocket, EmOptions),
{CbModule,_,_} = CbInfo,
- {ok, Socket} = CbModule:accept(ListenSocket, Timeout),
- inet:setopts(Socket, internal_inet_values()),
- {ok, Port} = inet:port(Socket),
- case ssl_connection_sup:start_child([server, "localhost", Port, Socket,
- {SslOpts, socket_options(InetValues)}, self(),
- CbInfo]) of
- {ok, Pid} ->
- CbModule:controlling_process(Socket, Pid),
- {ok, SslSocket#sslsocket{pid = Pid}};
- {error, Reason} ->
- {error, Reason}
+ case CbModule:accept(ListenSocket, Timeout) of
+ {ok, Socket} ->
+ inet:setopts(Socket, internal_inet_values()),
+ {ok, Port} = inet:port(Socket),
+ ConnArgs = [server, "localhost", Port, Socket,
+ {SslOpts, socket_options(InetValues)}, self(), CbInfo],
+ case ssl_connection_sup:start_child(ConnArgs) of
+ {ok, Pid} ->
+ CbModule:controlling_process(Socket, Pid),
+ {ok, SslSocket#sslsocket{pid = Pid}};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, Reason}
end;
transport_accept(#sslsocket{} = ListenSocket, Timeout) ->
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index dcf3331e6b..2d8f20bc29 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -87,7 +87,7 @@
user_data_buffer, % binary()
%% tls_buffer, % Keeps a lookahead one packet if available
log_alert, % boolean()
- renegotiation, % boolean()
+ renegotiation, % {boolean(), From | internal | peer}
recv_during_renegotiation, %boolean()
send_queue % queue()
}).
@@ -222,7 +222,7 @@ peer_certificate(ConnectionPid) ->
%% Description:
%%--------------------------------------------------------------------
renegotiation(ConnectionPid) ->
- send_all_state_event(ConnectionPid, renegotiate).
+ sync_send_all_state_event(ConnectionPid, renegotiate).
%%====================================================================
%% ssl_connection_sup API
@@ -383,32 +383,33 @@ abbreviated(Finished = #finished{},
#state{role = server,
negotiated_version = Version,
tls_handshake_hashes = Hashes,
- session = #session{master_secret = MasterSecret}} = State) ->
+ session = #session{master_secret = MasterSecret}} =
+ State0) ->
case ssl_handshake:verify_connection(Version, Finished, client,
MasterSecret, Hashes) of
verified ->
- ack_connection(State),
+ State = ack_connection(State0),
next_state_connection(State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, abbreviated, State),
- {stop, normal, State}
+ handle_own_alert(Alert, Version, abbreviated, State0),
+ {stop, normal, State0}
end;
abbreviated(Finished = #finished{},
#state{role = client, tls_handshake_hashes = Hashes0,
session = #session{master_secret = MasterSecret},
- negotiated_version = Version} = State) ->
+ negotiated_version = Version} = State0) ->
case ssl_handshake:verify_connection(Version, Finished, server,
MasterSecret, Hashes0) of
verified ->
- {ConnectionStates, Hashes} = finalize_client_handshake(State),
- ack_connection(State),
+ {ConnectionStates, Hashes} = finalize_client_handshake(State0),
+ State = ack_connection(State0),
next_state_connection(State#state{tls_handshake_hashes = Hashes,
connection_states =
ConnectionStates});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, abbreviated, State),
- {stop, normal, State}
+ handle_own_alert(Alert, Version, abbreviated, State0),
+ {stop, normal, State0}
end.
certify(socket_control, #state{role = server} = State) ->
@@ -442,7 +443,8 @@ certify(#certificate{} = Cert,
Opts#ssl_options.verify_fun) of
{PeerCert, PublicKeyInfo} ->
handle_peer_cert(PeerCert, PublicKeyInfo,
- State#state{client_certificate_requested = false});
+ State#state{client_certificate_requested
+ = false});
#alert{} = Alert ->
handle_own_alert(Alert, Version, certify_certificate, State),
{stop, normal, State}
@@ -606,19 +608,19 @@ cipher(#certificate_verify{signature = Signature},
end;
cipher(#finished{} = Finished,
- State = #state{negotiated_version = Version,
- host = Host,
- port = Port,
- role = Role,
- session = #session{master_secret = MasterSecret}
- = Session0,
- tls_handshake_hashes = Hashes}) ->
-
+ #state{negotiated_version = Version,
+ host = Host,
+ port = Port,
+ role = Role,
+ session = #session{master_secret = MasterSecret}
+ = Session0,
+ tls_handshake_hashes = Hashes} = State0) ->
+
case ssl_handshake:verify_connection(Version, Finished,
opposite_role(Role),
MasterSecret, Hashes) of
verified ->
- ack_connection(State),
+ State = ack_connection(State0),
Session = register_session(Role, Host, Port, Session0),
case Role of
client ->
@@ -627,15 +629,15 @@ cipher(#finished{} = Finished,
{NewConnectionStates, NewHashes} =
finalize_server_handshake(State#state{
session = Session}),
- NewState =
- State#state{connection_states = NewConnectionStates,
- session = Session,
- tls_handshake_hashes = NewHashes},
- next_state_connection(NewState)
+ next_state_connection(State#state{connection_states =
+ NewConnectionStates,
+ session = Session,
+ tls_handshake_hashes =
+ NewHashes})
end;
#alert{} = Alert ->
- handle_own_alert(Alert, Version, cipher, State),
- {stop, normal, State}
+ handle_own_alert(Alert, Version, cipher, State0),
+ {stop, normal, State0}
end.
connection(socket_control, #state{role = server} = State) ->
@@ -655,8 +657,7 @@ connection(#hello_request{}, State = #state{host = Host, port = Port,
Transport:send(Socket, BinMsg),
{next_state, hello, next_record(State#state{connection_states =
ConnectionStates1,
- tls_handshake_hashes = Hashes1,
- renegotiation = true})};
+ tls_handshake_hashes = Hashes1})};
connection(#client_hello{} = Hello, #state{role = server} = State) ->
hello(Hello, State).
@@ -681,16 +682,17 @@ handle_event(#ssl_tls{type = ?HANDSHAKE, fragment = Data},
%% This message should not be included in handshake
%% message hashes. Starts new handshake (renegotiation)
Hs0 = ssl_handshake:init_hashes(),
- ?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs0});
+ ?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs0,
+ renegotiation = {true, peer}});
({#hello_request{} = Packet, _}, {next_state, SName, State}) ->
%% This message should not be included in handshake
- %% message hashes. If allready in negotiation it will be ignored!
+ %% message hashes. Already in negotiation so it will be ignored!
?MODULE:SName(Packet, State);
({#client_hello{} = Packet, Raw}, {next_state, connection = SName, State}) ->
Hs0 = ssl_handshake:init_hashes(),
Hs1 = ssl_handshake:update_hashes(Hs0, Raw),
?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs1,
- renegotiation = true});
+ renegotiation = {true, peer}});
({Packet, Raw}, {next_state, SName, State = #state{tls_handshake_hashes=Hs0}}) ->
Hs1 = ssl_handshake:update_hashes(Hs0, Raw),
?MODULE:SName(Packet, State#state{tls_handshake_hashes=Hs1});
@@ -758,18 +760,23 @@ handle_event(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
_, #state{from = From, role = Role} = State) ->
alert_user(From, Alert, Role),
{stop, normal, State};
-handle_event(#alert{level = ?WARNING} = Alert, StateName,
+
+handle_event(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
+ #state{log_alert = Log, renegotiation = {true, internal}} = State) ->
+ log_alert(Log, StateName, Alert),
+ {stop, normal, State};
+
+handle_event(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
+ #state{log_alert = Log, renegotiation = {true, From}} = State) when is_pid(From) ->
+ log_alert(Log, StateName, Alert),
+ gen_fsm:reply(From, {error, renegotiation_rejected}),
+ {next_state, connection, next_record(State)};
+
+handle_event(#alert{level = ?WARNING, description = ?USER_CANCELED} = Alert, StateName,
#state{log_alert = Log} = State) ->
log_alert(Log, StateName, Alert),
-%%TODO: Could be user_canceled or no_negotiation should the latter be
- %% treated as fatal?!
- {next_state, StateName, next_record(State)};
-
-handle_event(renegotiate, connection, State) ->
- renegotiate(State);
-handle_event(renegotiate, StateName, State) ->
- %% Already in renegotiate ignore
- {next_state, StateName, State}.
+ {next_state, StateName, next_record(State)}.
+
%%--------------------------------------------------------------------
%% Function:
%% handle_sync_event(Event, From, StateName,
@@ -812,7 +819,8 @@ handle_sync_event({application_data, Data0}, From, connection,
ok
end,
renegotiate(State#state{connection_states = ConnectionStates,
- send_queue = queue:in_r({From, RestData}, SendQueue)})
+ send_queue = queue:in_r({From, RestData}, SendQueue),
+ renegotiation = {true, internal}})
end
catch throw:Error ->
{reply, Error, connection, State}
@@ -892,6 +900,12 @@ handle_sync_event({set_opts, Opts0}, _From, StateName,
end
end;
+handle_sync_event(renegotiate, From, connection, State) ->
+ renegotiate(State#state{renegotiation = {true, From}});
+
+handle_sync_event(renegotiate, _, StateName, State) ->
+ {reply, {error, already_renegotiating}, StateName, State};
+
handle_sync_event(info, _, StateName,
#state{negotiated_version = Version,
session = #session{cipher_suite = Suite}} = State) ->
@@ -1001,18 +1015,23 @@ handle_info(A, StateName, State) ->
%% necessary cleaning up. When it returns, the gen_fsm terminates with
%% Reason. The return value is ignored.
%%--------------------------------------------------------------------
-terminate(_Reason, connection, _S=#state{negotiated_version = Version,
+terminate(_Reason, connection, #state{negotiated_version = Version,
connection_states = ConnectionStates,
transport_cb = Transport,
- socket = Socket}) ->
+ socket = Socket, send_queue = SendQueue,
+ renegotiation = Renegotiate}) ->
+ notify_senders(SendQueue),
+ notify_renegotiater(Renegotiate),
{BinAlert, _} = encode_alert(?ALERT_REC(?WARNING,?CLOSE_NOTIFY),
Version, ConnectionStates),
Transport:send(Socket, BinAlert),
Transport:close(Socket);
-terminate(_Reason, _StateName, _S=#state{transport_cb = Transport,
- socket = Socket}) ->
- Transport:close(Socket),
- ok.
+terminate(_Reason, _StateName, #state{transport_cb = Transport,
+ socket = Socket, send_queue = SendQueue,
+ renegotiation = Renegotiate}) ->
+ notify_senders(SendQueue),
+ notify_renegotiater(Renegotiate),
+ Transport:close(Socket).
%%--------------------------------------------------------------------
%% Function:
@@ -1732,19 +1751,49 @@ get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Buffer)
end;
get_data(#socket_options{packet=Type, packet_size=Size}, _, Buffer) ->
PacketOpts = [{packet_size, Size}],
- case erlang:decode_packet(Type, Buffer, PacketOpts) of
+ case decode_packet(Type, Buffer, PacketOpts) of
{more, _} ->
{ok, <<>>, Buffer};
Decoded ->
Decoded
end.
-deliver_app_data(SO = #socket_options{active=once}, Data, Pid, From) ->
- send_or_reply(once, Pid, From, format_reply(SO, Data)),
- SO#socket_options{active=false};
-deliver_app_data(SO= #socket_options{active=Active}, Data, Pid, From) ->
- send_or_reply(Active, Pid, From, format_reply(SO, Data)),
- SO.
+decode_packet({http, headers}, Buffer, PacketOpts) ->
+ decode_packet(httph, Buffer, PacketOpts);
+decode_packet({http_bin, headers}, Buffer, PacketOpts) ->
+ decode_packet(httph_bin, Buffer, PacketOpts);
+decode_packet(Type, Buffer, PacketOpts) ->
+ erlang:decode_packet(Type, Buffer, PacketOpts).
+
+%% Just like with gen_tcp sockets, an ssl socket that has been configured with
+%% {packet, http} (or {packet, http_bin}) will automatically switch to expect
+%% HTTP headers after it sees a HTTP Request or HTTP Response line. We
+%% represent the current state as follows:
+%% #socket_options.packet =:= http: Expect a HTTP Request/Response line
+%% #socket_options.packet =:= {http, headers}: Expect HTTP Headers
+%% Note that if the user has explicitly configured the socket to expect
+%% HTTP headers using the {packet, httph} option, we don't do any automatic
+%% switching of states.
+deliver_app_data(SOpts = #socket_options{active=Active, packet=Type},
+ Data, Pid, From) ->
+ send_or_reply(Active, Pid, From, format_reply(SOpts, Data)),
+ SO = case Data of
+ {P, _, _, _} when ((P =:= http_request) or (P =:= http_response)),
+ ((Type =:= http) or (Type =:= http_bin)) ->
+ SOpts#socket_options{packet={Type, headers}};
+ http_eoh when tuple_size(Type) =:= 2 ->
+ % End of headers - expect another Request/Response line
+ {Type1, headers} = Type,
+ SOpts#socket_options{packet=Type1};
+ _ ->
+ SOpts
+ end,
+ case Active of
+ once ->
+ SO#socket_options{active=false};
+ _ ->
+ SO
+ end.
format_reply(#socket_options{active=false, mode=Mode, header=Header}, Data) ->
{ok, format_reply(Mode, Header, Data)};
@@ -1857,7 +1906,8 @@ next_state_connection(#state{send_queue = Queue0,
ok
end,
renegotiate(State#state{connection_states = ConnectionStates,
- send_queue = queue:in_r({From, RestData}, Queue)})
+ send_queue = queue:in_r({From, RestData}, Queue),
+ renegotiation = {true, internal}})
end;
{empty, Queue0} ->
next_state_is_connection(State)
@@ -1922,7 +1972,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions}, User,
user_data_buffer = <<>>,
log_alert = true,
session_cache_cb = SessionCacheCb,
- renegotiation = false,
+ renegotiation = {false, first},
recv_during_renegotiation = false,
send_queue = queue:new()
}.
@@ -1939,8 +1989,12 @@ get_socket_opts(Socket, [mode | Tags], SockOpts, Acc) ->
get_socket_opts(Socket, Tags, SockOpts,
[{mode, SockOpts#socket_options.mode} | Acc]);
get_socket_opts(Socket, [packet | Tags], SockOpts, Acc) ->
- get_socket_opts(Socket, Tags, SockOpts,
- [{packet, SockOpts#socket_options.packet} | Acc]);
+ case SockOpts#socket_options.packet of
+ {Type, headers} ->
+ get_socket_opts(Socket, Tags, SockOpts, [{packet, Type} | Acc]);
+ Type ->
+ get_socket_opts(Socket, Tags, SockOpts, [{packet, Type} | Acc])
+ end;
get_socket_opts(Socket, [header | Tags], SockOpts, Acc) ->
get_socket_opts(Socket, Tags, SockOpts,
[{header, SockOpts#socket_options.header} | Acc]);
@@ -2031,11 +2085,16 @@ mpint_binary(Binary) ->
<<?UINT32(Size), Binary/binary>>.
-ack_connection(#state{renegotiation = true}) ->
- ok;
-ack_connection(#state{renegotiation = false, from = From}) ->
- gen_fsm:reply(From, connected).
-
+ack_connection(#state{renegotiation = {true, Initiater}} = State)
+ when Initiater == internal;
+ Initiater == peer ->
+ State#state{renegotiation = undefined};
+ack_connection(#state{renegotiation = {true, From}} = State) ->
+ gen_fsm:reply(From, ok),
+ State#state{renegotiation = undefined};
+ack_connection(#state{renegotiation = {false, first}, from = From} = State) ->
+ gen_fsm:reply(From, connected),
+ State#state{renegotiation = undefined}.
renegotiate(#state{role = client} = State) ->
%% Handle same way as if server requested
@@ -2055,5 +2114,13 @@ renegotiate(#state{role = server,
Transport:send(Socket, BinMsg),
{next_state, hello, next_record(State#state{connection_states =
ConnectionStates,
- tls_handshake_hashes = Hs0,
- renegotiation = true})}.
+ tls_handshake_hashes = Hs0})}.
+notify_senders(SendQueue) ->
+ lists:foreach(fun({From, _}) ->
+ gen_fsm:reply(From, {error, closed})
+ end, queue:to_list(SendQueue)).
+
+notify_renegotiater({true, From}) when is_pid(From) ->
+ gen_fsm:reply(From, {error, closed});
+notify_renegotiater(_) ->
+ ok.
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index ff78375b9f..02f689f251 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -455,7 +455,7 @@ get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length),
Body:Length/binary,Rest/binary>>, KeyAlg,
Version, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
- H = dec_hs(Type, Body, key_excahange_alg(KeyAlg), Version),
+ H = dec_hs(Type, Body, key_exchange_alg(KeyAlg), Version),
get_tls_handshake_aux(Rest, KeyAlg, Version, [{H,Raw} | Acc]);
get_tls_handshake_aux(Data, _KeyAlg, _Version, Acc) ->
{lists:reverse(Acc), Data}.
@@ -960,10 +960,10 @@ sig_alg(Alg) when Alg == dh_dss; Alg == dhe_dss ->
sig_alg(_) ->
?NULL.
-key_excahange_alg(rsa) ->
+key_exchange_alg(rsa) ->
?KEY_EXCHANGE_RSA;
-key_excahange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
+key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
Alg == dh_dss; Alg == dh_rsa; Alg == dh_anon ->
?KEY_EXCHANGE_DIFFIE_HELLMAN;
-key_excahange_alg(_) ->
+key_exchange_alg(_) ->
?NULL.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 30a721b0b5..3f64a31448 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -155,7 +155,7 @@ all(suite) ->
upgrade, upgrade_with_timeout, tcp_connect,
ipv6, ekeyfile, ecertfile, ecacertfile, eoptions, shutdown,
shutdown_write, shutdown_both, shutdown_error, ciphers,
- send_close, dh_params,
+ send_close, close_transport_accept, dh_params,
server_verify_peer_passive,
server_verify_peer_active, server_verify_peer_active_once,
server_verify_none_passive, server_verify_none_active,
@@ -729,6 +729,32 @@ send_close(Config) when is_list(Config) ->
gen_tcp:close(TcpS),
{error, _} = ssl:send(SslS, "Hello world"),
ssl_test_lib:close(Server).
+
+%%--------------------------------------------------------------------
+close_transport_accept(doc) ->
+ ["Tests closing ssl socket when waiting on ssl:transport_accept/1"];
+
+close_transport_accept(suite) ->
+ [];
+
+close_transport_accept(Config) when is_list(Config) ->
+ ServerOpts = ?config(server_opts, Config),
+ {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
+
+ Port = 0,
+ Opts = [{active, false} | ServerOpts],
+ {ok, ListenSocket} = rpc:call(ServerNode, ssl, listen, [Port, Opts]),
+ spawn_link(fun() ->
+ test_server:sleep(?SLEEP),
+ rpc:call(ServerNode, ssl, close, [ListenSocket])
+ end),
+ case rpc:call(ServerNode, ssl, transport_accept, [ListenSocket]) of
+ {error, closed} ->
+ ok;
+ Other ->
+ exit({?LINE, Other})
+ end.
+
%%--------------------------------------------------------------------
dh_params(doc) ->
["Test to specify DH-params file in server."];
@@ -860,7 +886,7 @@ tcp_connect(Config) when is_list(Config) ->
Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
{from, self()},
{timeout, 5000},
- {mfa, {?MODULE, should_close, []}},
+ {mfa, {?MODULE, dummy, []}},
{tcp_options, TcpOpts},
{ssl_options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
@@ -869,18 +895,20 @@ tcp_connect(Config) when is_list(Config) ->
test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]),
gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"),
- ssl_test_lib:check_result(Server, {error,esslerrssl}, tcp_closed, Socket),
-
+ receive
+ {tcp_closed, Socket} ->
+ receive
+ {Server, {error, Error}} ->
+ test_server:format("Error ~p", [Error])
+ end
+ end,
ssl_test_lib:close(Server).
-should_close(Socket) ->
- receive
- {ssl, Socket, closed} ->
- server_closed;
- Other ->
- exit({?LINE, Other})
- end.
+dummy(Socket) ->
+ %% Should not happen as the ssl connection will not be established
+ %% due to fatal handshake failiure
+ exit(kill).
%%--------------------------------------------------------------------
ipv6(doc) ->
@@ -1046,8 +1074,6 @@ eoptions(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server0, {error, {eoptions, {active,trice}}},
Client0, {error, {eoptions, {active,trice}}}),
- test_server:sleep(?SLEEP),
-
Server1 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
{from, self()},
@@ -1059,9 +1085,6 @@ eoptions(Config) when is_list(Config) ->
{options, [{header, a} | ClientOpts]}]),
ssl_test_lib:check_result(Server1, {error, {eoptions, {header, a}}},
Client1, {error, {eoptions, {header, a}}}),
-
- test_server:sleep(?SLEEP),
-
Server2 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
@@ -1076,9 +1099,6 @@ eoptions(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server2, {error, {eoptions, {mode, a}}},
Client2, {error, {eoptions, {mode, a}}}),
-
- test_server:sleep(?SLEEP),
-
Server3 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
{from, self()},
@@ -1090,8 +1110,6 @@ eoptions(Config) when is_list(Config) ->
{options, [{packet, 8.0} | ClientOpts]}]),
ssl_test_lib:check_result(Server3, {error, {eoptions, {packet, 8.0}}},
Client3, {error, {eoptions, {packet, 8.0}}}),
-
- test_server:sleep(?SLEEP),
%% ssl
Server4 =
@@ -1105,8 +1123,6 @@ eoptions(Config) when is_list(Config) ->
{options, [{verify, 4} | ClientOpts]}]),
ssl_test_lib:check_result(Server4, {error, {eoptions, {verify, 4}}},
Client4, {error, {eoptions, {verify, 4}}}),
-
- test_server:sleep(?SLEEP),
Server5 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
@@ -1119,8 +1135,6 @@ eoptions(Config) when is_list(Config) ->
{options, [{depth, four} | ClientOpts]}]),
ssl_test_lib:check_result(Server5, {error, {eoptions, {depth, four}}},
Client5, {error, {eoptions, {depth, four}}}),
-
- test_server:sleep(?SLEEP),
Server6 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
@@ -1134,9 +1148,6 @@ eoptions(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server6, {error, {eoptions, {cacertfile, ""}}},
Client6, {error, {eoptions, {cacertfile, ""}}}),
-
- test_server:sleep(?SLEEP),
-
Server7 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
{from, self()},
@@ -1150,8 +1161,6 @@ eoptions(Config) when is_list(Config) ->
{error, {eoptions, {certfile, 'cert.pem'}}},
Client7, {error, {eoptions, {certfile, 'cert.pem'}}}),
- test_server:sleep(?SLEEP),
-
Server8 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
{from, self()},
@@ -1164,8 +1173,6 @@ eoptions(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server8,
{error, {eoptions, {keyfile, 'key.pem'}}},
Client8, {error, {eoptions, {keyfile, 'key.pem'}}}),
-
- test_server:sleep(?SLEEP),
Server9 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
@@ -1179,9 +1186,6 @@ eoptions(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server9, {error, {eoptions, {key, 'key.pem'}}},
Client9, {error, {eoptions, {key, 'key.pem'}}}),
-
- test_server:sleep(?SLEEP),
-
Server10 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
{from, self()},
@@ -1193,9 +1197,6 @@ eoptions(Config) when is_list(Config) ->
{options, [{password, foo} | ClientOpts]}]),
ssl_test_lib:check_result(Server10, {error, {eoptions, {password, foo}}},
Client10, {error, {eoptions, {password, foo}}}),
-
- test_server:sleep(?SLEEP),
-
%% Misc
Server11 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
@@ -1209,9 +1210,6 @@ eoptions(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server11, {error, {eoptions, {ssl_imp, cool}}},
Client11, {error, {eoptions, {ssl_imp, cool}}}),
-
- test_server:sleep(?SLEEP),
-
Server12 =
ssl_test_lib:start_server_error([{node, ServerNode}, {port, Port},
{from, self()},
@@ -2021,8 +2019,6 @@ client_renegotiate(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- test_server:sleep(?SLEEP),
-
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2059,8 +2055,6 @@ server_renegotiate(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- test_server:sleep(?SLEEP),
-
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2099,8 +2093,6 @@ client_no_wrap_sequence_number(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- test_server:sleep(?SLEEP),
-
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2142,8 +2134,6 @@ server_no_wrap_sequence_number(Config) when is_list(Config) ->
{options, [{renegotiate_at, N} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
- test_server:sleep(?SLEEP),
-
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -2160,13 +2150,11 @@ server_no_wrap_sequence_number(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
send_recv_result(Socket) ->
ssl:send(Socket, "Hello world"),
- test_server:sleep(?SLEEP),
{ok,"Hello world"} = ssl:recv(Socket, 11),
ok.
send_recv_result_active(Socket) ->
ssl:send(Socket, "Hello world"),
- test_server:sleep(?SLEEP),
receive
{ssl, Socket, "Hello world"} ->
ok
@@ -2174,7 +2162,6 @@ send_recv_result_active(Socket) ->
send_recv_result_active_once(Socket) ->
ssl:send(Socket, "Hello world"),
- test_server:sleep(?SLEEP),
receive
{ssl, Socket, "Hello world"} ->
ok
@@ -2182,18 +2169,22 @@ send_recv_result_active_once(Socket) ->
renegotiate(Socket, Data) ->
- [{session_id, Id} | _ ] = ssl:session_info(Socket),
- ssl:renegotiate(Socket),
+ test_server:format("Renegotiating ~n", []),
+ Result = ssl:renegotiate(Socket),
+ test_server:format("Result ~p~n", [Result]),
ssl:send(Socket, Data),
- test_server:sleep(1000),
- case ssl:session_info(Socket) of
- [{session_id, Id} | _ ] ->
- fail_session_not_renegotiated;
- _ ->
- ok
+ case Result of
+ ok ->
+ ok;
+ %% It is not an error in erlang ssl
+ %% if peer rejects renegotiation.
+ %% Connection will stay up
+ {error, renegotiation_rejected} ->
+ ok;
+ Other ->
+ Other
end.
-
session_cache_process_list(doc) ->
["Test reuse of sessions (short handshake)"];
@@ -2439,7 +2430,7 @@ erlang_ssl_receive(Socket, Data) ->
ok;
Other ->
test_server:fail({unexpected_message, Other})
- after 4000 ->
+ after ?SLEEP * 3 ->
test_server:fail({did_not_get, Data})
end.
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index f031552457..1bcb9a657b 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -144,7 +144,9 @@ all(suite) ->
packet_wait_passive, packet_wait_active,
packet_baddata_passive, packet_baddata_active,
packet_size_passive, packet_size_active,
- packet_erl_decode
+ packet_erl_decode,
+ packet_http_decode,
+ packet_http_bin_decode_multi
].
%% Test cases starts here.
@@ -1466,6 +1468,173 @@ client_packet_decode(Socket, CDR) ->
end,
ok.
+%%--------------------------------------------------------------------
+packet_http_decode(doc) ->
+ ["Test setting the packet option {packet, http}"];
+packet_http_decode(suite) ->
+ [];
+
+packet_http_decode(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Request = "GET / HTTP/1.1\r\n"
+ "host: www.example.com\r\n"
+ "user-agent: HttpTester\r\n"
+ "\r\n",
+ Response = "HTTP/1.1 200 OK\r\n"
+ "\r\n"
+ "Hello!",
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_http_decode, [Response]}},
+ {options, [{active, true}, binary, {packet, http} |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_decode, [Request]}},
+ {options, [{active, true}, binary, {packet, http} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+server_http_decode(Socket, HttpResponse) ->
+ assert_packet_opt(Socket, http),
+ receive
+ {ssl, Socket, {http_request, 'GET', _, {1,1}}} -> ok;
+ Other1 -> exit({?LINE, Other1})
+ end,
+ assert_packet_opt(Socket, http),
+ receive
+ {ssl, Socket, {http_header, _, 'Host', _, "www.example.com"}} -> ok;
+ Other2 -> exit({?LINE, Other2})
+ end,
+ assert_packet_opt(Socket, http),
+ receive
+ {ssl, Socket, {http_header, _, 'User-Agent', _, "HttpTester"}} -> ok;
+ Other3 -> exit({?LINE, Other3})
+ end,
+ assert_packet_opt(Socket, http),
+ receive
+ {ssl, Socket, http_eoh} -> ok;
+ Other4 -> exit({?LINE, Other4})
+ end,
+ assert_packet_opt(Socket, http),
+ ok = ssl:send(Socket, HttpResponse),
+ ok.
+
+client_http_decode(Socket, HttpRequest) ->
+ ok = ssl:send(Socket, HttpRequest),
+ receive
+ {ssl, Socket, {http_response, {1,1}, 200, "OK"}} -> ok;
+ Other1 -> exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, http_eoh} -> ok;
+ Other2 -> exit({?LINE, Other2})
+ end,
+ ok = ssl:setopts(Socket, [{packet, 0}]),
+ receive
+ {ssl, Socket, <<"Hello!">>} -> ok;
+ Other3 -> exit({?LINE, Other3})
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+packet_http_bin_decode_multi(doc) ->
+ ["Test setting the packet option {packet, http_bin} with multiple requests"];
+packet_http_bin_decode_multi(suite) ->
+ [];
+
+packet_http_bin_decode_multi(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Request = <<"GET / HTTP/1.1\r\n"
+ "host: www.example.com\r\n"
+ "user-agent: HttpTester\r\n"
+ "\r\n">>,
+ Response = <<"HTTP/1.1 200 OK\r\n"
+ "\r\n"
+ "Hello!">>,
+ NumMsgs = 3,
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, server_http_bin_decode, [Response, NumMsgs]}},
+ {options, [{active, true}, binary, {packet, http_bin} |
+ ServerOpts]}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, client_http_bin_decode, [Request, NumMsgs]}},
+ {options, [{active, true}, binary, {packet, http_bin} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+server_http_bin_decode(Socket, HttpResponse, Count) when Count > 0 ->
+ assert_packet_opt(Socket, http_bin),
+ receive
+ {ssl, Socket, {http_request, 'GET', _, {1,1}}} -> ok;
+ Other1 -> exit({?LINE, Other1})
+ end,
+ assert_packet_opt(Socket, http_bin),
+ receive
+ {ssl, Socket, {http_header, _, 'Host', _, <<"www.example.com">>}} -> ok;
+ Other2 -> exit({?LINE, Other2})
+ end,
+ assert_packet_opt(Socket, http_bin),
+ receive
+ {ssl, Socket, {http_header, _, 'User-Agent', _, <<"HttpTester">>}} -> ok;
+ Other3 -> exit({?LINE, Other3})
+ end,
+ assert_packet_opt(Socket, http_bin),
+ receive
+ {ssl, Socket, http_eoh} -> ok;
+ Other4 -> exit({?LINE, Other4})
+ end,
+ assert_packet_opt(Socket, http_bin),
+ ok = ssl:send(Socket, HttpResponse),
+ server_http_bin_decode(Socket, HttpResponse, Count - 1);
+server_http_bin_decode(_, _, _) ->
+ ok.
+
+client_http_bin_decode(Socket, HttpRequest, Count) when Count > 0 ->
+ ok = ssl:send(Socket, HttpRequest),
+ receive
+ {ssl, Socket, {http_response, {1,1}, 200, <<"OK">>}} -> ok;
+ Other1 -> exit({?LINE, Other1})
+ end,
+ receive
+ {ssl, Socket, http_eoh} -> ok;
+ Other2 -> exit({?LINE, Other2})
+ end,
+ ok = ssl:setopts(Socket, [{packet, 0}]),
+ receive
+ {ssl, Socket, <<"Hello!">>} -> ok;
+ Other3 -> exit({?LINE, Other3})
+ end,
+ ok = ssl:setopts(Socket, [{packet, http_bin}]),
+ client_http_bin_decode(Socket, HttpRequest, Count - 1);
+client_http_bin_decode(_, _, _) ->
+ ok.
%%--------------------------------------------------------------------
%% Internal functions
@@ -1572,3 +1741,6 @@ active_packet(Socket, Data, N) ->
Other ->
{other, Other, ssl:session_info(Socket),N}
end.
+
+assert_packet_opt(Socket, Type) ->
+ {ok, [{packet, Type}]} = ssl:getopts(Socket, [packet]).
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index f985058cd7..466e987e3e 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -52,7 +52,11 @@ node_to_hostip(Node) ->
Address.
start_server(Args) ->
- spawn_link(?MODULE, run_server, [Args]).
+ Result = spawn_link(?MODULE, run_server, [Args]),
+ receive
+ {listen, up} ->
+ Result
+ end.
run_server(Opts) ->
Node = proplists:get_value(node, Opts),
@@ -61,6 +65,7 @@ run_server(Opts) ->
Pid = proplists:get_value(from, Opts),
test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]),
{ok, ListenSocket} = rpc:call(Node, ssl, listen, [Port, Options]),
+ Pid ! {listen, up},
case Port of
0 ->
{ok, {_, NewPort}} = ssl:sockname(ListenSocket),
@@ -298,7 +303,11 @@ cert_options(Config) ->
start_upgrade_server(Args) ->
- spawn_link(?MODULE, run_upgrade_server, [Args]).
+ Result = spawn_link(?MODULE, run_upgrade_server, [Args]),
+ receive
+ {listen, up} ->
+ Result
+ end.
run_upgrade_server(Opts) ->
Node = proplists:get_value(node, Opts),
@@ -310,6 +319,7 @@ run_upgrade_server(Opts) ->
test_server:format("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]),
{ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]),
+ Pid ! {listen, up},
case Port of
0 ->
@@ -383,7 +393,11 @@ run_upgrade_client(Opts) ->
end.
start_server_error(Args) ->
- spawn_link(?MODULE, run_server_error, [Args]).
+ Result = spawn_link(?MODULE, run_server_error, [Args]),
+ receive
+ {listen, up} ->
+ Result
+ end.
run_server_error(Opts) ->
Node = proplists:get_value(node, Opts),
@@ -393,8 +407,9 @@ run_server_error(Opts) ->
test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]),
case rpc:call(Node, ssl, listen, [Port, Options]) of
{ok, ListenSocket} ->
- test_server:sleep(2000), %% To make sure error_client will
+ %% To make sure error_client will
%% get {error, closed} and not {error, connection_refused}
+ Pid ! {listen, up},
test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]),
case rpc:call(Node, ssl, transport_accept, [ListenSocket]) of
{error, _} = Error ->
@@ -405,6 +420,9 @@ run_server_error(Opts) ->
Pid ! {self(), Error}
end;
Error ->
+ %% Not really true but as this is an error test
+ %% this is what we want.
+ Pid ! {listen, up},
Pid ! {self(), Error}
end.
@@ -448,9 +466,19 @@ trigger_renegotiate(Socket, _, 0, Id) ->
test_server:sleep(1000),
case ssl:session_info(Socket) of
[{session_id, Id} | _ ] ->
+ %% If a warning alert is received
+ %% from openssl this may not be
+ %% an error!
fail_session_not_renegotiated;
- _ ->
- ok
+ %% Tests that uses this function will not reuse
+ %% sessions so if we get a new session id the
+ %% renegotiation has succeeded.
+ [{session_id, _} | _ ] ->
+ ok;
+ {error, closed} ->
+ fail_session_fatal_alert_during_renegotiation;
+ {error, timeout} ->
+ fail_timeout
end;
trigger_renegotiate(Socket, ErlData, N, Id) ->
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index adb5b9cd13..624404b556 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -327,7 +327,7 @@ erlang_client_openssl_server_no_wrap_sequence_number(Config) when is_list(Config
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- ErlData = "From erlang to openssl",
+ ErlData = "From erlang to openssl\n",
N = 10,
Port = ssl_test_lib:inet_port(node()),
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 6b76dffd86..d385064ae9 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -19,7 +19,11 @@
SSL_VSN = 3.11
-TICKETS = OTP-8517 OTP-7046
+TICKETS = OTP-8517 \
+ OTP-7046 \
+ OTP-8557 \
+ OTP-8560 \
+ OTP-8545
#TICKETS_3.10.9 = OTP-8510
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index e1b569d389..f144cbb938 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -109,6 +109,8 @@ format_error(cannot_parse) ->
io_lib:format("cannot parse file, giving up", []);
format_error({bad,W}) ->
io_lib:format("badly formed '~s'", [W]);
+format_error(missing_parenthesis) ->
+ io_lib:format("badly formed define: missing closing right parenthesis",[]);
format_error({call,What}) ->
io_lib:format("illegal macro call '~s'",[What]);
format_error({undefined,M,none}) ->
@@ -415,7 +417,7 @@ scan_toks(From, St) ->
leave_file(From, St#epp{location=Cl});
{error,_E} ->
epp_reply(From, {error,{St#epp.location,epp,cannot_parse}}),
- leave_file(From, St) %This serious, just exit!
+ leave_file(wait_request(St), St) %This serious, just exit!
end.
scan_toks([{'-',_Lh},{atom,_Ld,define}=Define|Toks], From, St) ->
@@ -491,26 +493,32 @@ scan_extends(_Ts, _As, Ms) -> Ms.
scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St)
when Type =:= atom; Type =:= var ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok, Defs} when is_list(Defs) ->
- %% User defined macros: can be overloaded
- case proplists:is_defined(none, Defs) of
- true ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
+ case catch macro_expansion(Toks) of
+ Expansion when is_list(Expansion) ->
+ case dict:find({atom,M}, St#epp.macs) of
+ {ok, Defs} when is_list(Defs) ->
+ %% User defined macros: can be overloaded
+ case proplists:is_defined(none, Defs) of
+ true ->
+ epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
+ wait_req_scan(St);
+ false ->
+ scan_define_cont(From, St,
+ {atom, M},
+ {none, {none,Expansion}})
+ end;
+ {ok, _PreDef} ->
+ %% Predefined macros: cannot be overloaded
+ epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
wait_req_scan(St);
- false ->
+ error ->
scan_define_cont(From, St,
{atom, M},
- {none, {none,macro_expansion(Toks)}})
+ {none, {none,Expansion}})
end;
- {ok, _PreDef} ->
- %% Predefined macros: cannot be overloaded
- epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St,
- {atom, M},
- {none, {none,macro_expansion(Toks)}})
+ {error,ErrL,What} ->
+ epp_reply(From, {error,{ErrL,epp,What}}),
+ wait_req_scan(St)
end;
scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
when Type =:= atom; Type =:= var ->
@@ -536,6 +544,9 @@ scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
error ->
scan_define_cont(From, St, {atom, M}, {Len, {As, Me}})
end;
+ {error,ErrL,What} ->
+ epp_reply(From, {error,{ErrL,epp,What}}),
+ wait_req_scan(St);
_ ->
epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
wait_req_scan(St)
@@ -789,7 +800,7 @@ skip_toks(From, St, [I|Sis]) ->
leave_file(From, St#epp{location=Cl,istk=[I|Sis]});
{error,_E} ->
epp_reply(From, {error,{St#epp.location,epp,cannot_parse}}),
- leave_file(From, St) %This serious, just exit!
+ leave_file(wait_request(St), St) %This serious, just exit!
end;
skip_toks(From, St, []) ->
scan_toks(From, St).
@@ -816,7 +827,7 @@ macro_pars([{var,_L,Name}, {',',_}|Ts], Args) ->
macro_pars(Ts, [Name|Args]).
macro_expansion([{')',_Lp},{dot,_Ld}]) -> [];
-macro_expansion([{dot,_Ld}]) -> []; %Be nice, allow no right paren!
+macro_expansion([{dot,Ld}]) -> throw({error,Ld,missing_parenthesis});
macro_expansion([T|Ts]) ->
[T|macro_expansion(Ts)].
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 3342e8f1ff..4806b5d361 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -23,7 +23,8 @@
upcase_mac/1, upcase_mac_1/1, upcase_mac_2/1,
variable/1, variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
- otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1]).
+ otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
+ otp_8562/1]).
-export([epp_parse_erl_form/2]).
@@ -63,7 +64,7 @@ all(doc) ->
all(suite) ->
[rec_1, upcase_mac, predef_mac, variable, otp_4870, otp_4871, otp_5362,
pmod, not_circular, skip_header, otp_6277, otp_7702, otp_8130,
- overload_mac, otp_8388, otp_8470, otp_8503].
+ overload_mac, otp_8388, otp_8470, otp_8503, otp_8562].
rec_1(doc) ->
["Recursive macros hang or crash epp (OTP-1398)."];
@@ -616,9 +617,9 @@ otp_8130(Config) when is_list(Config) ->
"t() -> 14 = (#file_info{size = 14})#file_info.size, ok.\n">>,
ok},
- {otp_8130_7,
+ {otp_8130_7_new,
<<"-record(b, {b}).\n"
- "-define(A, {{a,#b.b.\n"
+ "-define(A, {{a,#b.b).\n"
"t() -> {{a,2}} = ?A}}, ok.">>,
ok},
@@ -750,7 +751,14 @@ otp_8130(Config) when is_list(Config) ->
{otp_8130_c24,
<<"\n-include(\"no such file.erl\").\n">>,
- {errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}}
+ {errors,[{{2,2},epp,{include,file,"no such file.erl"}}],[]}},
+
+ {otp_8130_7,
+ <<"-record(b, {b}).\n"
+ "-define(A, {{a,#b.b.\n"
+ "t() -> {{a,2}} = ?A}}, ok.">>,
+ {errors,[{{2,20},epp,missing_parenthesis},
+ {{3,19},epp,{undefined,'A',none}}],[]}}
],
?line [] = compile(Config, Cs),
@@ -1047,13 +1055,13 @@ overload_mac(Config) when is_list(Config) ->
"-undef(A).\n"
"t1() -> ?A.\n",
"t2() -> ?A(1).">>,
- {errors,[{{4,9},epp,{undefined,'A', none}},
- {{5,9},epp,{undefined,'A', 1}}],[]}},
+ {errors,[{{4,10},epp,{undefined,'A', none}},
+ {{5,10},epp,{undefined,'A', 1}}],[]}},
%% cannot overload predefined macros
{overload_mac_c2,
<<"-define(MODULE(X), X).">>,
- {errors,[{{1,9},epp,{redefine_predef,'MODULE'}}],[]}},
+ {errors,[{{1,50},epp,{redefine_predef,'MODULE'}}],[]}},
%% cannot overload macros with same arity
{overload_mac_c3,
@@ -1120,27 +1128,27 @@ otp_8388(Config) when is_list(Config) ->
{macro_1,
<<"-define(m(A), A).\n"
"t() -> ?m(,).\n">>,
- {errors,[{{2,11},epp,{arg_error,m}}],[]}},
+ {errors,[{{2,9},epp,{arg_error,m}}],[]}},
{macro_2,
<<"-define(m(A), A).\n"
"t() -> ?m(a,).\n">>,
- {errors,[{{2,12},epp,{arg_error,m}}],[]}},
+ {errors,[{{2,9},epp,{arg_error,m}}],[]}},
{macro_3,
<<"-define(LINE, a).\n">>,
- {errors,[{{1,9},epp,{redefine_predef,'LINE'}}],[]}},
+ {errors,[{{1,50},epp,{redefine_predef,'LINE'}}],[]}},
{macro_4,
<<"-define(A(B, C, D), {B,C,D}).\n"
"t() -> ?A(a,,3).\n">>,
- {errors,[{{2,8},epp,{mismatch,'A'}}],[]}},
+ {errors,[{{2,9},epp,{mismatch,'A'}}],[]}},
{macro_5,
<<"-define(Q, {?F0(), ?F1(,,4)}).\n">>,
- {errors,[{{1,24},epp,{arg_error,'F1'}}],[]}},
+ {errors,[{{1,62},epp,{arg_error,'F1'}}],[]}},
{macro_6,
<<"-define(FOO(X), ?BAR(X)).\n"
"-define(BAR(X), ?FOO(X)).\n"
"-undef(FOO).\n"
"test() -> ?BAR(1).\n">>,
- {errors,[{{4,11},epp,{undefined,'FOO',1}}],[]}}
+ {errors,[{{4,12},epp,{undefined,'FOO',1}}],[]}}
],
?line [] = compile(Config, Ts),
ok.
@@ -1175,6 +1183,20 @@ otp_8503(Config) when is_list(Config) ->
?line receive _ -> fail() after 0 -> ok end,
ok.
+otp_8562(doc) ->
+ ["OTP-8503. Record with no fields is considered typed."];
+otp_8562(suite) ->
+ [];
+otp_8562(Config) when is_list(Config) ->
+ Cs = [{otp_8562,
+ <<"-define(P(), {a,b}.\n"
+ "-define(P3, .\n">>,
+ {errors,[{{1,60},epp,missing_parenthesis},
+ {{2,13},epp,missing_parenthesis}], []}}
+ ],
+ ?line [] = compile(Config, Cs),
+ ok.
+
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 3106c72bd8..207f6fdf16 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -31,6 +31,30 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.2.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ All Erlang files are now built by the test server instead of the test directory Makefile.
+ </p>
+ <p>
+ Erlang files in data directories are now built by the test suites instead of using
+ prebuilt versions under version control.
+ </p>
+ <p>
+ Removed a number of obsolete guards.
+ </p>
+ <p>
+ Own Id: OTP-8537
+ </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.2.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 4162b52a80..83b9d4826f 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -17,14 +17,17 @@
# %CopyrightEnd%
#
-XMERL_VSN = 1.2.4
+XMERL_VSN = 1.2.5
TICKETS = \
- OTP-8343
+ OTP-8537
+
+TICKETS_1.2.5 = \
+ OTP-8537
TICKETS_1.2.4 = \
- OTP-8343
+ OTP-8343
TICKETS_1.2.3 = \
OTP-8251 \