diff --git a/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp b/openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp
index 9678287..33a289f 100644
--- openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp
+++ openjdk/hotspot/src/share/vm/classfile/classFileParser.cpp
@@ -944,11 +944,12 @@ void ClassFileParser::parse_field_attributes(u2 attributes_count,
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
+ cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
parsed_annotations,
CHECK);
- cfs->skip_u1(runtime_visible_annotations_length, CHECK);
+ cfs->skip_u1_fast(runtime_visible_annotations_length);
} else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
@@ -1655,6 +1656,11 @@ int ClassFileParser::skip_annotation(u1* buffer, int limit, int index) {
return index;
}
+// Safely increment index by val if does not pass limit
+#define SAFE_ADD(index, limit, val) \
+if (index >= limit - val) return limit; \
+index += val;
+
// Skip an annotation value. Return >=limit if there is any problem.
int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
// value := switch (tag:u1) {
@@ -1665,19 +1671,19 @@ int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
// case @: annotation;
// case s: s_con:u2;
// }
- if ((index += 1) >= limit) return limit; // read tag
+ SAFE_ADD(index, limit, 1); // read tag
u1 tag = buffer[index-1];
switch (tag) {
case 'B': case 'C': case 'I': case 'S': case 'Z':
case 'D': case 'F': case 'J': case 'c': case 's':
- index += 2; // skip con or s_con
+ SAFE_ADD(index, limit, 2); // skip con or s_con
break;
case 'e':
- index += 4; // skip e_class, e_name
+ SAFE_ADD(index, limit, 4); // skip e_class, e_name
break;
case '[':
{
- if ((index += 2) >= limit) return limit; // read nval
+ SAFE_ADD(index, limit, 2); // read nval
int nval = Bytes::get_Java_u2(buffer+index-2);
while (--nval >= 0 && index < limit) {
index = skip_annotation_value(buffer, limit, index);
@@ -1699,8 +1705,8 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit,
ClassFileParser::AnnotationCollector* coll,
TRAPS) {
// annotations := do(nann:u2) {annotation}
- int index = 0;
- if ((index += 2) >= limit) return; // read nann
+ int index = 2;
+ if (index >= limit) return; // read nann
int nann = Bytes::get_Java_u2(buffer+index-2);
enum { // initial annotation layout
atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;'
@@ -1719,7 +1725,8 @@ void ClassFileParser::parse_annotations(u1* buffer, int limit,
s_size = 9,
min_size = 6 // smallest possible size (zero members)
};
- while ((--nann) >= 0 && (index-2 + min_size <= limit)) {
+ // Cannot add min_size to index in case of overflow MAX_INT
+ while ((--nann) >= 0 && (index-2 <= limit - min_size)) {
int index0 = index;
index = skip_annotation(buffer, limit, index);
u1* abase = buffer + index0;
@@ -2324,10 +2331,11 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
runtime_visible_annotations_length = method_attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
+ cfs->guarantee_more(runtime_visible_annotations_length, CHECK_(nullHandle));
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length, &parsed_annotations,
CHECK_(nullHandle));
- cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
+ cfs->skip_u1_fast(runtime_visible_annotations_length);
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = method_attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
@@ -2953,11 +2961,12 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio
runtime_visible_annotations_length = attribute_length;
runtime_visible_annotations = cfs->get_u1_buffer();
assert(runtime_visible_annotations != NULL, "null visible annotations");
+ cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
parse_annotations(runtime_visible_annotations,
runtime_visible_annotations_length,
parsed_annotations,
CHECK);
- cfs->skip_u1(runtime_visible_annotations_length, CHECK);
+ cfs->skip_u1_fast(runtime_visible_annotations_length);
} else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) {
runtime_invisible_annotations_length = attribute_length;
runtime_invisible_annotations = cfs->get_u1_buffer();
diff --git a/openjdk/hotspot/src/share/vm/classfile/stackMapFrame.cpp b/openjdk/hotspot/src/share/vm/classfile/stackMapFrame.cpp
index 1332a08..f5d108b 100644
--- openjdk/hotspot/src/share/vm/classfile/stackMapFrame.cpp
+++ openjdk/hotspot/src/share/vm/classfile/stackMapFrame.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -155,47 +155,8 @@ int StackMapFrame::is_assignable_to(
return i;
}
-bool StackMapFrame::has_flag_match_exception(
- const StackMapFrame* target) const {
- // We allow flags of {UninitThis} to assign to {} if-and-only-if the
- // target frame does not depend upon the current type.
- // This is slightly too strict, as we need only enforce that the
- // slots that were initialized by the <init> (the things that were
- // UninitializedThis before initialize_object() converted them) are unused.
- // However we didn't save that information so we'll enforce this upon
- // anything that might have been initialized. This is a rare situation
- // and javac never generates code that would end up here, but some profilers
- // (such as NetBeans) might, when adding exception handlers in <init>
- // methods to cover the invokespecial instruction. See 7020118.
-
- assert(max_locals() == target->max_locals() &&
- stack_size() == target->stack_size(), "StackMap sizes must match");
-
- VerificationType top = VerificationType::top_type();
- VerificationType this_type = verifier()->current_type();
-
- if (!flag_this_uninit() || target->flags() != 0) {
- return false;
- }
-
- for (int i = 0; i < target->locals_size(); ++i) {
- if (locals()[i] == this_type && target->locals()[i] != top) {
- return false;
- }
- }
-
- for (int i = 0; i < target->stack_size(); ++i) {
- if (stack()[i] == this_type && target->stack()[i] != top) {
- return false;
- }
- }
-
- return true;
-}
-
bool StackMapFrame::is_assignable_to(
- const StackMapFrame* target, bool is_exception_handler,
- ErrorContext* ctx, TRAPS) const {
+ const StackMapFrame* target, ErrorContext* ctx, TRAPS) const {
if (_max_locals != target->max_locals()) {
*ctx = ErrorContext::locals_size_mismatch(
_offset, (StackMapFrame*)this, (StackMapFrame*)target);
@@ -226,8 +187,7 @@ bool StackMapFrame::is_assignable_to(
return false;
}
- bool match_flags = (_flags | target->flags()) == target->flags();
- if (match_flags || is_exception_handler && has_flag_match_exception(target)) {
+ if ((_flags | target->flags()) == target->flags()) {
return true;
} else {
*ctx = ErrorContext::bad_flags(target->offset(),
diff --git a/openjdk/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/openjdk/hotspot/src/share/vm/classfile/stackMapFrame.hpp
index 24cbae3..d6e18ae 100644
--- openjdk/hotspot/src/share/vm/classfile/stackMapFrame.hpp
+++ openjdk/hotspot/src/share/vm/classfile/stackMapFrame.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -167,8 +167,7 @@ class StackMapFrame : public ResourceObj {
// Return true if this stack map frame is assignable to target.
bool is_assignable_to(
- const StackMapFrame* target, bool is_exception_handler,
- ErrorContext* ctx, TRAPS) const;
+ const StackMapFrame* target, ErrorContext* ctx, TRAPS) const;
inline void set_mark() {
#ifdef ASSERT
@@ -290,8 +289,6 @@ class StackMapFrame : public ResourceObj {
int is_assignable_to(
VerificationType* src, VerificationType* target, int32_t len, TRAPS) const;
- bool has_flag_match_exception(const StackMapFrame* target) const;
-
TypeOrigin stack_top_ctx();
void print_on(outputStream* str) const;
diff --git a/openjdk/hotspot/src/share/vm/classfile/stackMapTable.cpp b/openjdk/hotspot/src/share/vm/classfile/stackMapTable.cpp
index 1c92b61..547dcf6 100644
--- openjdk/hotspot/src/share/vm/classfile/stackMapTable.cpp
+++ openjdk/hotspot/src/share/vm/classfile/stackMapTable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -70,26 +70,25 @@ int StackMapTable::get_index_from_offset(int32_t offset) const {
bool StackMapTable::match_stackmap(
StackMapFrame* frame, int32_t target,
- bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
+ bool match, bool update, ErrorContext* ctx, TRAPS) const {
int index = get_index_from_offset(target);
- return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD);
+ return match_stackmap(frame, target, index, match, update, ctx, THREAD);
}
// Match and/or update current_frame to the frame in stackmap table with
// specified offset and frame index. Return true if the two frames match.
-// handler is true if the frame in stackmap_table is for an exception handler.
//
-// The values of match and update are: _match__update__handler
+// The values of match and update are: _match__update
//
-// checking a branch target: true false false
-// checking an exception handler: true false true
+// checking a branch target: true false
+// checking an exception handler: true false
// linear bytecode verification following an
-// unconditional branch: false true false
+// unconditional branch: false true
// linear bytecode verification not following an
-// unconditional branch: true true false
+// unconditional branch: true true
bool StackMapTable::match_stackmap(
StackMapFrame* frame, int32_t target, int32_t frame_index,
- bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
+ bool match, bool update, ErrorContext* ctx, TRAPS) const {
if (frame_index < 0 || frame_index >= _frame_count) {
*ctx = ErrorContext::missing_stackmap(frame->offset());
frame->verifier()->verify_error(
@@ -102,7 +101,7 @@ bool StackMapTable::match_stackmap(
if (match) {
// Has direct control flow from last instruction, need to match the two
// frames.
- result = frame->is_assignable_to(stackmap_frame, handler,
+ result = frame->is_assignable_to(stackmap_frame,
ctx, CHECK_VERIFY_(frame->verifier(), result));
}
if (update) {
@@ -126,7 +125,7 @@ void StackMapTable::check_jump_target(
StackMapFrame* frame, int32_t target, TRAPS) const {
ErrorContext ctx;
bool match = match_stackmap(
- frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier()));
+ frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
if (!match || (target < 0 || target >= _code_length)) {
frame->verifier()->verify_error(ctx,
"Inconsistent stackmap frames at branch target %d", target);
diff --git a/openjdk/hotspot/src/share/vm/classfile/stackMapTable.hpp b/openjdk/hotspot/src/share/vm/classfile/stackMapTable.hpp
index ba1cf38..81e380b 100644
--- openjdk/hotspot/src/share/vm/classfile/stackMapTable.hpp
+++ openjdk/hotspot/src/share/vm/classfile/stackMapTable.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -77,12 +77,12 @@ class StackMapTable : public StackObj {
// specified offset. Return true if the two frames match.
bool match_stackmap(
StackMapFrame* current_frame, int32_t offset,
- bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
+ bool match, bool update, ErrorContext* ctx, TRAPS) const;
// Match and/or update current_frame to the frame in stackmap table with
// specified offset and frame index. Return true if the two frames match.
bool match_stackmap(
StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
- bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
+ bool match, bool update, ErrorContext* ctx, TRAPS) const;
// Check jump instructions. Make sure there are no uninitialized
// instances on backward branch.
diff --git a/openjdk/hotspot/src/share/vm/classfile/verifier.cpp b/openjdk/hotspot/src/share/vm/classfile/verifier.cpp
index 75a8411..cfe6e8c 100644
--- openjdk/hotspot/src/share/vm/classfile/verifier.cpp
+++ openjdk/hotspot/src/share/vm/classfile/verifier.cpp
@@ -507,19 +507,13 @@ void ErrorContext::stackmap_details(outputStream* ss, const Method* method) cons
stack_map_frame* sm_frame = sm_table->entries();
streamIndentor si2(ss);
int current_offset = -1;
- // Subtract two from StackMapAttribute length because the length includes
- // two bytes for number of table entries.
- size_t sm_table_space = method->stackmap_data()->length() - 2;
+ address end_of_sm_table = (address)sm_table + method->stackmap_data()->length();
for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
ss->indent();
- size_t sm_frame_size = sm_frame->size();
- // If the size of the next stackmap exceeds the length of the entire
- // stackmap table then print a truncated message and return.
- if (sm_frame_size > sm_table_space) {
+ if (!sm_frame->verify((address)sm_frame, end_of_sm_table)) {
sm_frame->print_truncated(ss, current_offset);
return;
}
- sm_table_space -= sm_frame_size;
sm_frame->print_on(ss, current_offset);
ss->cr();
current_offset += sm_frame->offset_delta();
@@ -1823,7 +1817,7 @@ u2 ClassVerifier::verify_stackmap_table(u2 stackmap_index, u2 bci,
// If matched, current_frame will be updated by this method.
bool matches = stackmap_table->match_stackmap(
current_frame, this_offset, stackmap_index,
- !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0));
+ !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0));
if (!matches) {
// report type error
verify_error(ctx, "Instruction type does not match stack map");
@@ -1870,7 +1864,7 @@ void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, S
}
ErrorContext ctx;
bool matches = stackmap_table->match_stackmap(
- new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this));
+ new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this));
if (!matches) {
verify_error(ctx, "Stack map does not match the one at "
"exception handler %d", handler_pc);
diff --git a/openjdk/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp b/openjdk/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp
index 406ac73..fc86a50 100644
--- openjdk/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp
+++ openjdk/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -148,7 +148,9 @@ void G1ParScanThreadState::trim_queue() {
do {
// Drain the overflow stack first, so other threads can steal.
while (_refs->pop_overflow(ref)) {
- dispatch_reference(ref);
+ if (!_refs->try_push_to_taskqueue(ref)) {
+ dispatch_reference(ref);
+ }
}
while (_refs->pop_local(ref)) {
diff --git a/openjdk/hotspot/src/share/vm/utilities/taskqueue.hpp b/openjdk/hotspot/src/share/vm/utilities/taskqueue.hpp
index fb9ea61..8bdb38d 100644
--- openjdk/hotspot/src/share/vm/utilities/taskqueue.hpp
+++ openjdk/hotspot/src/share/vm/utilities/taskqueue.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -453,6 +453,9 @@ public:
// Push task t onto the queue or onto the overflow stack. Return true.
inline bool push(E t);
+ // Try to push task t onto the queue only. Returns true if successful, false otherwise.
+ inline bool try_push_to_taskqueue(E t);
+
// Attempt to pop from the overflow stack; return true if anything was popped.
inline bool pop_overflow(E& t);
@@ -486,6 +489,10 @@ bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
return true;
}
+template <class E, MEMFLAGS F, unsigned int N>
+bool OverflowTaskQueue<E, F, N>::try_push_to_taskqueue(E t) {
+ return taskqueue_t::push(t);
+}
class TaskQueueSetSuper {
protected:
static int randomParkAndMiller(int* seed0);
diff --git a/openjdk/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java b/openjdk/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java
index 5fc7268..9c3e8f7 100644
--- openjdk/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java
+++ openjdk/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8075118
- * @summary Allow a ctor to call super() from a switch bytecode.
+ * @summary JVM stuck in infinite loop during verification
* @compile HandlerInTry.jasm
* @compile IsolatedHandlerInTry.jasm
* @run main/othervm -Xverify:all LoadHandlerInTry
@@ -70,9 +70,10 @@ public class LoadHandlerInTry {
System.out.println("Regression test for bug 8075118");
try {
Class newClass = Class.forName("HandlerInTry");
- } catch (Exception e) {
- System.out.println("Failed: Exception was thrown: " + e.toString());
- throw e;
+ throw new RuntimeException(
+ "Failed to throw VerifyError for HandlerInTry");
+ } catch (java.lang.VerifyError e) {
+ System.out.println("Passed: VerifyError exception was thrown");
}
try {
diff --git a/openjdk/jdk/make/data/tzdata/VERSION b/openjdk/jdk/make/data/tzdata/VERSION
index 6bf3661..3fbffda 100644
--- openjdk/jdk/make/data/tzdata/VERSION
+++ openjdk/jdk/make/data/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2016f
+tzdata2016i
diff --git a/openjdk/jdk/make/data/tzdata/africa b/openjdk/jdk/make/data/tzdata/africa
index b523dc3..cbde238 100644
--- openjdk/jdk/make/data/tzdata/africa
+++ openjdk/jdk/make/data/tzdata/africa
@@ -487,7 +487,7 @@ Zone Africa/Monrovia -0:43:08 - LMT 1882
# http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/
#
# From Paul Eggert (2013-10-25):
-# For now, assume they're reverting to the pre-2012 rules of permanent UTC+2.
+# For now, assume they're reverting to the pre-2012 rules of permanent UT +02.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Libya 1951 only - Oct 14 2:00 1:00 S
diff --git a/openjdk/jdk/make/data/tzdata/antarctica b/openjdk/jdk/make/data/tzdata/antarctica
index e12c764..2398ac5 100644
--- openjdk/jdk/make/data/tzdata/antarctica
+++ openjdk/jdk/make/data/tzdata/antarctica
@@ -33,9 +33,7 @@
# http://www.spri.cam.ac.uk/bob/periant.htm
# for information.
# Unless otherwise specified, we have no time zone information.
-#
-# Except for the French entries,
-# I made up all time zone abbreviations mentioned here; corrections welcome!
+
# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
# Argentina - year-round bases
@@ -52,7 +50,7 @@
# previously sealers and scientific personnel wintered
# Margaret Turner reports
# http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
-# (1999-09-30) that they're UTC+5, with no DST;
+# (1999-09-30) that they're UT +05, with no DST;
# presumably this is when they have visitors.
#
# year-round bases
@@ -89,25 +87,29 @@
# Background:
# http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
+# From Steffen Thorsen (2016-10-28):
+# Australian Antarctica Division informed us that Casey changed time
+# zone to UTC+11 in "the morning of 22nd October 2016".
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - -00 1969
- 8:00 - AWST 2009 Oct 18 2:00
- # Australian Western Std Time
- 11:00 - CAST 2010 Mar 5 2:00 # Casey Time
- 8:00 - AWST 2011 Oct 28 2:00
- 11:00 - CAST 2012 Feb 21 17:00u
- 8:00 - AWST
+ 8:00 - +08 2009 Oct 18 2:00
+ 11:00 - +11 2010 Mar 5 2:00
+ 8:00 - +08 2011 Oct 28 2:00
+ 11:00 - +11 2012 Feb 21 17:00u
+ 8:00 - +08 2016 Oct 22
+ 11:00 - +11
Zone Antarctica/Davis 0 - -00 1957 Jan 13
- 7:00 - DAVT 1964 Nov # Davis Time
+ 7:00 - +07 1964 Nov
0 - -00 1969 Feb
- 7:00 - DAVT 2009 Oct 18 2:00
- 5:00 - DAVT 2010 Mar 10 20:00u
- 7:00 - DAVT 2011 Oct 28 2:00
- 5:00 - DAVT 2012 Feb 21 20:00u
- 7:00 - DAVT
+ 7:00 - +07 2009 Oct 18 2:00
+ 5:00 - +05 2010 Mar 10 20:00u
+ 7:00 - +07 2011 Oct 28 2:00
+ 5:00 - +05 2012 Feb 21 20:00u
+ 7:00 - +07
Zone Antarctica/Mawson 0 - -00 1954 Feb 13
- 6:00 - MAWT 2009 Oct 18 2:00 # Mawson Time
- 5:00 - MAWT
+ 6:00 - +06 2009 Oct 18 2:00
+ 5:00 - +05
# References:
# Casey Weather (1998-02-26)
# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
@@ -161,7 +163,7 @@ Zone Antarctica/Mawson 0 - -00 1954 Feb 13
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
- 5:00 - TFT # ISO code TF Time
+ 5:00 - +05
#
# year-round base in the main continent
# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
@@ -172,9 +174,9 @@ Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/DumontDUrville 0 - -00 1947
- 10:00 - PMT 1952 Jan 14 # Port-Martin Time
+ 10:00 - +10 1952 Jan 14
0 - -00 1956 Nov
- 10:00 - DDUT # Dumont-d'Urville Time
+ 10:00 - +10
# France & Italy - year-round base
# Concordia, -750600+1232000, since 2005
@@ -200,7 +202,7 @@ Zone Antarctica/DumontDUrville 0 - -00 1947
# station of Japan, it's appropriate for the principal location.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Syowa 0 - -00 1957 Jan 29
- 3:00 - SYOT # Syowa Time
+ 3:00 - +03
# See:
# NIPR Antarctic Research Activities (1999-08-17)
# http://www.nipr.ac.jp/english/ara01.html
@@ -237,17 +239,17 @@ Zone Antarctica/Syowa 0 - -00 1957 Jan 29
# correct, but they should be quite close to the actual dates.
#
# From Paul Eggert (2014-03-21):
-# The CET-switching Troll rules require zic from tzcode 2014b or later, so as
+# The CET-switching Troll rules require zic from tz 2014b or later, so as
# suggested by Bengt-Inge Larsson comment them out for now, and approximate
# with only UTC and CEST. Uncomment them when 2014b is more prevalent.
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-#Rule Troll 2005 max - Mar 1 1:00u 1:00 CET
-Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST
-#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 CET
-#Rule Troll 2004 max - Nov 7 1:00u 0:00 UTC
+#Rule Troll 2005 max - Mar 1 1:00u 1:00 +01
+Rule Troll 2005 max - Mar lastSun 1:00u 2:00 +02
+#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 +01
+#Rule Troll 2004 max - Nov 7 1:00u 0:00 +00
# Remove the following line when uncommenting the above '#Rule' lines.
-Rule Troll 2004 max - Oct lastSun 1:00u 0:00 UTC
+Rule Troll 2004 max - Oct lastSun 1:00u 0:00 +00
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Troll 0 - -00 2005 Feb 12
0:00 Troll %s
@@ -288,10 +290,10 @@ Zone Antarctica/Troll 0 - -00 2005 Feb 12
# changes during the year and does not necessarily correspond to mean
# solar noon. So the Vostok time might have been whatever the clocks
# happened to be during their visit. So we still don't really know what time
-# it is at Vostok. But we'll guess UTC+6.
+# it is at Vostok. But we'll guess +06.
#
Zone Antarctica/Vostok 0 - -00 1957 Dec 16
- 6:00 - VOST # Vostok time
+ 6:00 - +06
# S Africa - year-round bases
# Marion Island, -4653+03752
@@ -324,7 +326,7 @@ Zone Antarctica/Vostok 0 - -00 1957 Dec 16
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Rothera 0 - -00 1976 Dec 1
- -3:00 - ROTT # Rothera time
+ -3:00 - -03
# Uruguay - year round base
# Artigas, King George Island, -621104-0585107
diff --git a/openjdk/jdk/make/data/tzdata/asia b/openjdk/jdk/make/data/tzdata/asia
index 35ac37c..7d54032 100644
--- openjdk/jdk/make/data/tzdata/asia
+++ openjdk/jdk/make/data/tzdata/asia
@@ -139,13 +139,11 @@ Zone Asia/Kabul 4:36:48 - LMT 1890
# http://www.worldtimezone.com/dst_news/dst_news_armenia03.html
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2
- 3:00 - YERT 1957 Mar # Yerevan Time
- 4:00 RussiaAsia YER%sT 1991 Mar 31 2:00s
- 3:00 1:00 YERST 1991 Sep 23 # independence
- 3:00 RussiaAsia AM%sT 1995 Sep 24 2:00s
- 4:00 - AMT 1997
- 4:00 RussiaAsia AM%sT 2012 Feb 9
- 4:00 - AMT
+ 3:00 - +03 1957 Mar
+ 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
+ 3:00 RussiaAsia +03/+04 1995 Sep 24 2:00s
+ 4:00 - +04 1997
+ 4:00 RussiaAsia +04/+05
# Azerbaijan
@@ -166,13 +164,12 @@ Rule Azer 1997 2015 - Mar lastSun 4:00 1:00 S
Rule Azer 1997 2015 - Oct lastSun 5:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Baku 3:19:24 - LMT 1924 May 2
- 3:00 - BAKT 1957 Mar # Baku Time
- 4:00 RussiaAsia BAK%sT 1991 Mar 31 2:00s
- 3:00 1:00 BAKST 1991 Aug 30 # independence
- 3:00 RussiaAsia AZ%sT 1992 Sep lastSun 2:00s
- 4:00 - AZT 1996 # Azerbaijan Time
- 4:00 EUAsia AZ%sT 1997
- 4:00 Azer AZ%sT
+ 3:00 - +03 1957 Mar
+ 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
+ 3:00 RussiaAsia +03/+04 1992 Sep lastSun 2:00s
+ 4:00 - +04 1996
+ 4:00 EUAsia +04/+05 1997
+ 4:00 Azer +04/+05
# Bahrain
# See Asia/Qatar.
@@ -291,7 +288,7 @@ Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
# Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Rangoon 6:24:40 - LMT 1880 # or Yangon
+Zone Asia/Yangon 6:24:40 - LMT 1880 # or Rangoon
6:24:40 - RMT 1920 # Rangoon Mean Time?
6:30 - BURT 1942 May # Burma Time
9:00 - JST 1945 May 3
@@ -406,7 +403,7 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
# different - the occupied districts going by Tokyo time, an hour
# ahead of that prevailing in the rest of Shanghai." Guess that the
-# Xujiahui Observatory was under French control and stuck with UT+8.
+# Xujiahui Observatory was under French control and stuck with UT +08.
#
# In earlier versions of this file, China had many separate Zone entries, but
# this was based on what were apparently incorrect data in Shanks & Pottenger.
@@ -415,26 +412,26 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Proposed in 1918 and theoretically in effect until 1949 (although in practice
# mainly observed in coastal areas), the five zones were:
#
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT +08:30
# Asia/Harbin (currently a link to Asia/Shanghai)
# Heilongjiang (except Mohe county), Jilin
#
-# Zhongyuan Time ("Central plain Time") UT+8
+# Zhongyuan Time ("Central plain Time") UT +08
# Asia/Shanghai
# most of China
# This currently represents most other zones as well,
# as apparently these regions have been the same since 1970.
# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
-# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+# Guo says Shanghai switched to UT +08 "from the end of the 19th century".
#
-# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Long-shu Time (probably due to Long and Shu being two names of the area) UT +07
# Asia/Chongqing (currently a link to Asia/Shanghai)
# Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
# most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
# counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
# Yangchun, Yangjiang, Yu'nan, and Yunfu.
#
-# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Xin-zang Time ("Xinjiang-Tibet Time") UT +06
# Asia/Urumqi
# This currently represents Kunlun Time as well,
# as apparently the two regions have been the same since 1970.
@@ -447,7 +444,7 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
# Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
#
-# Kunlun Time UT+5.5
+# Kunlun Time UT +05:30
# Asia/Kashgar (currently a link to Asia/Urumqi)
# West Tibet, including Pulan, Aheqi, Shufu, Shule;
# West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
@@ -463,7 +460,7 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
#
# On the other hand, ethnic Uyghurs, who make up about half the
# population of Xinjiang, typically use "Xinjiang time" which is two
-# hours behind Beijing time, or UTC +0600. The government of the Xinjiang
+# hours behind Beijing time, or UT +06. The government of the Xinjiang
# Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
# local governments such as the Ürümqi city government use both times in
# publications, referring to what is popularly called Xinjiang time as
@@ -519,8 +516,8 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# having the same time as Beijing.
# From Paul Eggert (2014-06-30):
-# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
-# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# In the early days of the PRC, Tibet was given its own time zone (UT +06)
+# but this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
@@ -534,12 +531,12 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
# China, and tracking down all these organizations' timekeeping rules would be
# quite a trick. Approximate this lost history by a transition from LMT to
-# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# UT +06 at the start of 1928, the year of accession of the warlord Jin Shuren,
# which happens to be the date given by Shanks & Pottenger (no doubt as a
-# guess) as the transition from LMT. Ignore the usage of UT+8 before
-# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# guess) as the transition from LMT. Ignore the usage of +08 before
+# 1986-02-01 under the theory that the transition date to +08 is unknown and
# that the sort of users who prefer Asia/Urumqi now typically ignored the
-# UT+8 mandate back then.
+# +08 mandate back then.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
# Beijing time, used throughout China; represented by Shanghai.
@@ -744,7 +741,7 @@ Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30
# be found from historical government announcement database.
# From Paul Eggert (2014-07-03):
-# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# As per Yu-Cheng Chuang, say that Taiwan was at UT +09 from 1937-10-01
# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
@@ -797,9 +794,19 @@ Zone Asia/Macau 7:34:20 - LMT 1912 Jan 1
###############################################################################
# Cyprus
-#
+
# Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT.
+# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+
+# From Paul Eggert (2016-09-09):
+# Yesterday's Cyprus Mail reports that Northern Cyprus followed Turkey's
+# lead and switched from +02/+03 to +03 year-round.
+# http://cyprus-mail.com/2016/09/08/two-time-zones-cyprus-turkey-will-not-turn-clocks-back-next-month/
#
+# From Even Scharning (2016-10-31):
+# Looks like the time zone split in Cyprus went through last night.
+# http://cyprus-mail.com/2016/10/30/cyprus-new-division-two-time-zones-now-reality/
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Cyprus 1975 only - Apr 13 0:00 1:00 S
Rule Cyprus 1975 only - Oct 12 0:00 0 -
@@ -814,7 +821,10 @@ Rule Cyprus 1981 1998 - Mar lastSun 0:00 1:00 S
Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14
2:00 Cyprus EE%sT 1998 Sep
2:00 EUAsia EE%sT
-# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+Zone Asia/Famagusta 2:15:48 - LMT 1921 Nov 14
+ 2:00 Cyprus EE%sT 1998 Sep
+ 2:00 EUAsia EE%sT 2016 Sep 8
+ 3:00 - +03
# Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72.
# However, for various reasons many users expect to find it under Europe.
@@ -858,16 +868,15 @@ Link Asia/Nicosia Europe/Nicosia
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Tbilisi 2:59:11 - LMT 1880
2:59:11 - TBMT 1924 May 2 # Tbilisi Mean Time
- 3:00 - TBIT 1957 Mar # Tbilisi Time
- 4:00 RussiaAsia TBI%sT 1991 Mar 31 2:00s
- 3:00 1:00 TBIST 1991 Apr 9 # independence
- 3:00 RussiaAsia GE%sT 1992 # Georgia Time
- 3:00 E-EurAsia GE%sT 1994 Sep lastSun
- 4:00 E-EurAsia GE%sT 1996 Oct lastSun
- 4:00 1:00 GEST 1997 Mar lastSun
- 4:00 E-EurAsia GE%sT 2004 Jun 27
- 3:00 RussiaAsia GE%sT 2005 Mar lastSun 2:00
- 4:00 - GET
+ 3:00 - +03 1957 Mar
+ 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
+ 3:00 RussiaAsia +03/+04 1992
+ 3:00 E-EurAsia +03/+04 1994 Sep lastSun
+ 4:00 E-EurAsia +04/+05 1996 Oct lastSun
+ 4:00 1:00 +05 1997 Mar lastSun
+ 4:00 E-EurAsia +04/+05 2004 Jun 27
+ 3:00 RussiaAsia +03/+04 2005 Mar lastSun 2:00
+ 4:00 - +04
# East Timor
@@ -944,7 +953,7 @@ Zone Asia/Kolkata 5:53:28 - LMT 1880 # Kolkata
# These would be the earliest possible times for a change.
# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
# Traditionnelles, 1987, Paris) says that Java and Madura switched
-# from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
+# from UT +09 to +07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
# (Hollandia). For now, assume all Indonesian locations other than Jayapura
# switched on 1945-09-23.
#
@@ -955,11 +964,11 @@ Zone Asia/Kolkata 5:53:28 - LMT 1880 # Kolkata
# summary published by the Time and Frequency Laboratory of the
# Research Center for Calibration, Instrumentation and Metrology,
# Indonesia, <http://time.kim.lipi.go.id/time-eng.php> (2006-09-29).
-# The abbreviations are:
+# The time zone abbreviations and UT offsets are:
#
-# WIB - UTC+7 - Waktu Indonesia Barat (Indonesia western time)
-# WITA - UTC+8 - Waktu Indonesia Tengah (Indonesia central time)
-# WIT - UTC+9 - Waktu Indonesia Timur (Indonesia eastern time)
+# WIB - +07 - Waktu Indonesia Barat (Indonesia western time)
+# WITA - +08 - Waktu Indonesia Tengah (Indonesia central time)
+# WIT - +09 - Waktu Indonesia Timur (Indonesia eastern time)
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
# Java, Sumatra
@@ -1848,11 +1857,11 @@ Rule Kyrgyz 1997 2005 - Mar lastSun 2:30 1:00 S
Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
- 5:00 - FRUT 1930 Jun 21 # Frunze Time
- 6:00 RussiaAsia FRU%sT 1991 Mar 31 2:00s
- 5:00 1:00 FRUST 1991 Aug 31 2:00 # independence
- 5:00 Kyrgyz KG%sT 2005 Aug 12 # Kyrgyzstan Time
- 6:00 - KGT
+ 5:00 - +05 1930 Jun 21
+ 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s
+ 5:00 RussiaAsia +05/+06 1991 Aug 31 2:00
+ 5:00 Kyrgyz +05/+06 2005 Aug 12
+ 6:00 - +06
###############################################################################
@@ -1891,25 +1900,24 @@ Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S
Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
-# From Paul Eggert (2014-10-30):
+# From Paul Eggert (2016-08-23):
# The Korean Wikipedia entry gives the following sources for UT offsets:
#
-# 1908: Official Journal Article No. 3994 (Edict No. 5)
+# 1908: Official Journal Article No. 3994 (decree No. 5)
# 1912: Governor-General of Korea Official Gazette Issue No. 367
# (Announcement No. 338)
# 1954: Presidential Decree No. 876 (1954-03-17)
# 1961: Law No. 676 (1961-08-07)
-# 1987: Law No. 3919 (1986-12-31)
#
-# The Wikipedia entry also has confusing information about a change
-# to UT+9 in April 1910, but then what would be the point of the later change
-# to UT+9 on 1912-01-01? Omit the 1910 change for now.
+# (Another source "1987: Law No. 3919 (1986-12-31)" was in the 2014-10-30
+# edition of the Korean Wikipedia entry.)
#
# I guessed that time zone abbreviations through 1945 followed the same
# rules as discussed under Taiwan, with nominal switches from JST to KST
# when the respective cities were taken over by the Allies after WWII.
#
-# For Pyongyang we have no information; guess no changes since World War II.
+# For Pyongyang, guess no changes from World War II until 2015, as we
+# have no information otherwise.
# From Steffen Thorsen (2015-08-07):
# According to many news sources, North Korea is going to change to
@@ -2069,7 +2077,7 @@ Zone Indian/Maldives 4:54:00 - LMT 1880 # Male
# Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
# there is only one time zone and that DST is observed, citing Microsoft
# Windows XP as the source. Risto Nykänen (2005-05-16) reports that
-# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
+# travelmongolia.org says there are two time zones (UT +07, +08) with no DST.
# Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
# Washington, DC says there are two time zones, with DST observed.
# He also found
@@ -2572,11 +2580,6 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# From Paul Eggert (2015-03-03):
# http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014
# says that the fall 2014 transition was Oct 23 at 24:00.
-# For future dates, guess the last Friday in March at 24:00 through
-# the first Friday on or after October 21 at 00:00. This is consistent with
-# the predictions in today's editions of the following URLs:
-# http://www.timeanddate.com/time/change/gaza-strip/gaza
-# http://www.timeanddate.com/time/change/west-bank/hebron
# From Hannah Kreitem (2016-03-09):
# http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728
@@ -2586,7 +2589,21 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
#
# From Paul Eggert (2016-03-12):
# Predict spring transitions on March's last Saturday at 01:00 from now on.
-# Leave fall predictions alone for now.
+
+# From Sharef Mustafa (2016-10-19):
+# [T]he Palestinian cabinet decision (Mar 8th 2016) published on
+# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf
+# states that summer time will end on Oct 29th at 01:00.
+#
+# From Tim Parenti (2016-10-19):
+# Predict fall transitions on October's last Saturday at 01:00 from now on.
+# This is consistent with the 2016 transition as well as our spring
+# predictions.
+#
+# From Paul Eggert (2016-10-19):
+# It's also consistent with predictions in the following URLs today:
+# http://www.timeanddate.com/time/change/gaza-strip/gaza
+# http://www.timeanddate.com/time/change/west-bank/hebron
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
@@ -2615,9 +2632,10 @@ Rule Palestine 2011 only - Sep 30 0:00 0 -
Rule Palestine 2012 2014 - Mar lastThu 24:00 1:00 S
Rule Palestine 2012 only - Sep 21 1:00 0 -
Rule Palestine 2013 only - Sep Fri>=21 0:00 0 -
-Rule Palestine 2014 max - Oct Fri>=21 0:00 0 -
+Rule Palestine 2014 2015 - Oct Fri>=21 0:00 0 -
Rule Palestine 2015 only - Mar lastFri 24:00 1:00 S
Rule Palestine 2016 max - Mar lastSat 1:00 1:00 S
+Rule Palestine 2016 max - Oct lastSat 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@@ -2705,7 +2723,7 @@ Link Asia/Qatar Asia/Bahrain
# earlier date.
#
# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
-# time zones; the other zone, at UTC+4, was in the far eastern part of
+# time zones; the other zone, at UT +04, was in the far eastern part of
# the country. Ignore this, as it's before our 1970 cutoff.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -2767,45 +2785,31 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
# People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
# as that zone has agreed with the Tamil areas since our cutoff date of 1970.
-# From K Sethu (2006-04-25):
-# I think the abbreviation LKT originated from the world of computers at
-# the time of or subsequent to the time zone changes by SL Government
-# twice in 1996 and probably SL Government or its standardization
-# agencies never declared an abbreviation as a national standard.
-#
-# I recollect before the recent change the government announcements
-# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
-# Time and no mention was made about the abbreviation.
-#
-# If we look at Sri Lanka Department of Government's "Official News
-# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
-# use SLT as abbreviation in time stamp at the beginning of each news
-# item....
-#
-# Within Sri Lanka I think LKT is well known among computer users and
-# administrators. In my opinion SLT may not be a good choice because the
-# nation's largest telcom / internet operator Sri Lanka Telcom is well
-# known by that abbreviation - simply as SLT (there IP domains are
-# slt.lk and sltnet.lk).
-#
-# But if indeed our government has adopted SLT as standard abbreviation
-# (that we have not known so far) then it is better that it be used for
-# all computers.
-
-# From Paul Eggert (2006-04-25):
-# One possibility is that we wait for a bit for the dust to settle down
-# and then see what people actually say in practice.
+# From Sadika Sumanapala (2016-10-19):
+# According to http://www.sltime.org (maintained by Measurement Units,
+# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka
+# standard time is SLST.
+#
+# From Paul Eggert (2016-10-18):
+# "SLST" seems to be reasonably recent and rarely-used outside time
+# zone nerd sources. I searched Google News and found three uses of
+# it in the International Business Times of India in February and
+# March of this year when discussing cricket match times, but nothing
+# since then (though there has been a lot of cricket) and nothing in
+# other English-language news sources. Our old abbreviation "LKT" is
+# even worse. For now, let's use a numeric abbreviation; we can
+# switch to "SLST" if it catches on.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Colombo 5:19:24 - LMT 1880
5:19:32 - MMT 1906 # Moratuwa Mean Time
- 5:30 - IST 1942 Jan 5
- 5:30 0:30 IHST 1942 Sep
- 5:30 1:00 IST 1945 Oct 16 2:00
- 5:30 - IST 1996 May 25 0:00
- 6:30 - LKT 1996 Oct 26 0:30
- 6:00 - LKT 2006 Apr 15 0:30
- 5:30 - IST
+ 5:30 - +0530 1942 Jan 5
+ 5:30 0:30 +0530/+06 1942 Sep
+ 5:30 1:00 +0530/+0630 1945 Oct 16 2:00
+ 5:30 - +0530 1996 May 25 0:00
+ 6:30 - +0630 1996 Oct 26 0:30
+ 6:00 - +06 2006 Apr 15 0:30
+ 5:30 - +0530
# Syria
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -2974,10 +2978,10 @@ Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
# From Shanks & Pottenger.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2
- 5:00 - DUST 1930 Jun 21 # Dushanbe Time
- 6:00 RussiaAsia DUS%sT 1991 Mar 31 2:00s
- 5:00 1:00 DUSST 1991 Sep 9 2:00s
- 5:00 - TJT # Tajikistan Time
+ 5:00 - +05 1930 Jun 21
+ 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s
+ 5:00 1:00 +05/+06 1991 Sep 9 2:00s
+ 5:00 - +05
# Thailand
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -2991,11 +2995,10 @@ Link Asia/Bangkok Asia/Vientiane # Laos
# From Shanks & Pottenger.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad
- 4:00 - ASHT 1930 Jun 21 # Ashkhabad Time
- 5:00 RussiaAsia ASH%sT 1991 Mar 31 2:00
- 4:00 RussiaAsia ASH%sT 1991 Oct 27 # independence
- 4:00 RussiaAsia TM%sT 1992 Jan 19 2:00
- 5:00 - TMT
+ 4:00 - +04 1930 Jun 21
+ 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00
+ 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00
+ 5:00 - +05
# United Arab Emirates
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -3007,20 +3010,18 @@ Link Asia/Dubai Asia/Muscat # Oman
# Byalokoz 1919 says Uzbekistan was 4:27:53.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Samarkand 4:27:53 - LMT 1924 May 2
- 4:00 - SAMT 1930 Jun 21 # Samarkand Time
- 5:00 - SAMT 1981 Apr 1
- 5:00 1:00 SAMST 1981 Oct 1
- 6:00 - TAST 1982 Apr 1 # Tashkent Time
- 5:00 RussiaAsia SAM%sT 1991 Sep 1 # independence
- 5:00 RussiaAsia UZ%sT 1992
- 5:00 - UZT
+ 4:00 - +04 1930 Jun 21
+ 5:00 - +05 1981 Apr 1
+ 5:00 1:00 +06 1981 Oct 1
+ 6:00 - +06 1982 Apr 1
+ 5:00 RussiaAsia +05/+06 1992
+ 5:00 - +05
# Milne says Tashkent was 4:37:10.8; round to nearest.
Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2
- 5:00 - TAST 1930 Jun 21 # Tashkent Time
- 6:00 RussiaAsia TAS%sT 1991 Mar 31 2:00
- 5:00 RussiaAsia TAS%sT 1991 Sep 1 # independence
- 5:00 RussiaAsia UZ%sT 1992
- 5:00 - UZT
+ 5:00 - +05 1930 Jun 21
+ 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00
+ 5:00 RussiaAsia +05/+06 1992
+ 5:00 - +05
# Vietnam
diff --git a/openjdk/jdk/make/data/tzdata/australasia b/openjdk/jdk/make/data/tzdata/australasia
index 134a01e..81ef521 100644
--- openjdk/jdk/make/data/tzdata/australasia
+++ openjdk/jdk/make/data/tzdata/australasia
@@ -373,7 +373,13 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# commencing at 2.00 am on Sunday 1st November, 2015 and ending at
# 3.00 am on Sunday 17th January, 2016.
-# From Paul Eggert (2015-09-01):
+# From Raymond Kumar (2016-10-04):
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx
+# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when
+# clocks go forward an hour at 2am to 3am.... Daylight Saving will
+# end at 3.00am on Sunday 15th January 2017."
+
+# From Paul Eggert (2016-10-03):
# For now, guess DST from 02:00 the first Sunday in November to
# 03:00 the third Sunday in January. Although ad hoc, it matches
# transitions since late 2014 and seems more likely to match future
@@ -568,7 +574,7 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
# Base the Bougainville entry on the Arawa-Kieta region, which appears to have
# the most people even though it was devastated in the Bougainville Civil War.
#
-# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates
+# Although Shanks gives 1942-03-15 / 1943-11-01 for UT +09, these dates
# are apparently rough guesswork from the starts of military campaigns.
# The World War II entries below are instead based on Arawa-Kieta.
# The Japanese occupied Kieta in July 1942,
@@ -576,8 +582,8 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
# http://pwencycl.kgbudge.com/B/o/Bougainville.htm
# and seem to have controlled it until their 1945-08-21 surrender.
#
-# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11
-# on 2014-12-28 at 02:00. They call UTC+11 "Bougainville Standard Time";
+# The Autonomous Region of Bougainville switched from UT +10 to +11
+# on 2014-12-28 at 02:00. They call +11 "Bougainville Standard Time";
# abbreviate this as BST. See:
# http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/
#
@@ -643,7 +649,7 @@ Link Pacific/Pago_Pago Pacific/Midway # in US minor outlying islands
# From Paul Eggert (2014-06-27):
# The International Date Line Act 2011
# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
-# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# changed Samoa from UT -11 to +13, effective "12 o'clock midnight, on
# Thursday 29th December 2011". The International Date Line was adjusted
# accordingly.
@@ -719,11 +725,13 @@ Rule Tonga 1999 only - Oct 7 2:00s 1:00 S
Rule Tonga 2000 only - Mar 19 2:00s 0 -
Rule Tonga 2000 2001 - Nov Sun>=1 2:00 1:00 S
Rule Tonga 2001 2002 - Jan lastSun 2:00 0 -
+Rule Tonga 2016 max - Nov Sun>=1 2:00 1:00 S
+Rule Tonga 2017 max - Jan Sun>=15 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Tongatapu 12:19:20 - LMT 1901
- 12:20 - TOT 1941 # Tonga Time
- 13:00 - TOT 1999
- 13:00 Tonga TO%sT
+ 12:20 - +1220 1941
+ 13:00 - +13 1999
+ 13:00 Tonga +13/+14
# Tuvalu
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -738,7 +746,7 @@ Zone Pacific/Funafuti 11:56:52 - LMT 1901
# 1886-1891; Baker was similar but exact dates are not known.
# Inhabited by civilians 1935-1942; U.S. military bases 1943-1944;
# uninhabited thereafter.
-# Howland observed Hawaii Standard Time (UT-10:30) in 1937;
+# Howland observed Hawaii Standard Time (UT -10:30) in 1937;
# see page 206 of Elgen M. Long and Marie K. Long,
# Amelia Earhart: the Mystery Solved, Simon & Schuster (2000).
# So most likely Howland and Baker observed Hawaii Time from 1935
@@ -1496,7 +1504,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# Zealand time. I understand that is the time they keep locally, anyhow."
# For now, assume this practice goes back to the introduction of standard time
# in New Zealand, as this would make Chatham Islands time almost exactly match
-# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# LMT back when New Zealand was at UT +11:30; also, assume Chatham Islands did
# not observe New Zealand's prewar DST.
###############################################################################
@@ -1552,7 +1560,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# For now, we assume the Ladrones switched at the same time as the Philippines;
# see Asia/Manila.
-# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time,
+# US Public Law 106-564 (2000-12-23) made UT +10 the official standard time,
# under the name "Chamorro Standard Time". There is no official abbreviation,
# but Congressman Robert A. Underwood, author of the bill that became law,
# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
@@ -1564,15 +1572,15 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# "I am certain, having lived there for the past decade, that 'Truk'
# (now properly known as Chuuk) ... is in the time zone GMT+10."
#
-# Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
+# Shanks & Pottenger write that Truk switched from UT +10 to +11
# on 1978-10-01; ignore this for now.
# From Paul Eggert (1999-10-29):
# The Federated States of Micronesia Visitors Board writes in
# The Federated States of Micronesia - Visitor Information (1999-01-26)
# http://www.fsmgov.org/info/clocks.html
-# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
-# We don't know when Kosrae switched from UTC+12; assume January 1 for now.
+# that Truk and Yap are UT +10, and Ponape and Kosrae are +11.
+# We don't know when Kosrae switched from +12; assume January 1 for now.
# Midway
@@ -1638,11 +1646,11 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# ordaining - by a masterpiece of diplomatic flattery - that
# the Fourth of July should be celebrated twice in that year."
-# Although Shanks & Pottenger says they both switched to UTC-11:30
-# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# Although Shanks & Pottenger says they both switched to UT -11:30
+# in 1911, and to -11 in 1950. many earlier sources give -11
# for American Samoa, e.g., the US National Bureau of Standards
# circular "Standard Time Throughout the World", 1932.
-# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# Assume American Samoa switched to -11 in 1911, not 1950,
# and that after 1950 they agreed until (western) Samoa skipped a
# day in 2011. Assume also that the Samoas follow the US and New
# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
@@ -1729,9 +1737,17 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# of January the standard time in the Kingdom shall be moved backward by one
# hour to 1:00am.
-# From Pulu 'Anau (2002-11-05):
+# From Pulu ʻAnau (2002-11-05):
# The law was for 3 years, supposedly to get renewed. It wasn't.
+# From Pulu ʻAnau (2016-10-27):
+# http://mic.gov.to/news-today/press-releases/6375-daylight-saving-set-to-run-from-6-november-2016-to-15-january-2017
+# Cannot find anyone who knows the rules, has seen the duration or has seen
+# the cabinet decision, but it appears we are following Fiji's rule set.
+#
+# From Tim Parenti (2016-10-26):
+# Assume Tonga will observe DST from the first Sunday in November at 02:00
+# through the third Sunday in January at 03:00, like Fiji, for now.
# Wake
diff --git a/openjdk/jdk/make/data/tzdata/backward b/openjdk/jdk/make/data/tzdata/backward
index 8352705..ec96c7e 100644
--- openjdk/jdk/make/data/tzdata/backward
+++ openjdk/jdk/make/data/tzdata/backward
@@ -59,6 +59,7 @@ Link Asia/Shanghai Asia/Harbin
Link Asia/Urumqi Asia/Kashgar
Link Asia/Kathmandu Asia/Katmandu
Link Asia/Macau Asia/Macao
+Link Asia/Yangon Asia/Rangoon
Link Asia/Ho_Chi_Minh Asia/Saigon
Link Asia/Jerusalem Asia/Tel_Aviv
Link Asia/Thimphu Asia/Thimbu
diff --git a/openjdk/jdk/make/data/tzdata/etcetera b/openjdk/jdk/make/data/tzdata/etcetera
index d2fb91c..ec31f1b 100644
--- openjdk/jdk/make/data/tzdata/etcetera
+++ openjdk/jdk/make/data/tzdata/etcetera
@@ -31,6 +31,13 @@
# need now for the entries that are not on UTC are for ships at sea
# that cannot use POSIX TZ settings.
+# Starting with POSIX 1003.1-2001, the entries below are all
+# unnecessary as settings for the TZ environment variable. E.g.,
+# instead of TZ='Etc/GMT+4' one can use the POSIX setting TZ='<-04>+4'.
+#
+# Do not use a POSIX TZ setting like TZ='GMT+4', which is four hours
+# behind GMT but uses the completely misleading abbreviation "GMT".
+
Zone Etc/GMT 0 - GMT
Zone Etc/UTC 0 - UTC
Zone Etc/UCT 0 - UCT
@@ -49,23 +56,13 @@ Link Etc/GMT Etc/GMT-0
Link Etc/GMT Etc/GMT+0
Link Etc/GMT Etc/GMT0
-# We use POSIX-style signs in the Zone names and the output abbreviations,
+# Be consistent with POSIX TZ settings in the Zone names,
# even though this is the opposite of what many people expect.
# POSIX has positive signs west of Greenwich, but many people expect
# positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses
-# the abbreviation "GMT+4" and corresponds to 4 hours behind UT
+# the abbreviation "-04" and corresponds to 4 hours behind UT
# (i.e. west of Greenwich) even though many people would expect it to
# mean 4 hours ahead of UT (i.e. east of Greenwich).
-#
-# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for
-# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to
-# ISO 8601 you can use TZ='<-0400>+4'. Thus the commonly-expected
-# offset is kept within the angle bracket (and is used for display)
-# while the POSIX sign is kept outside the angle bracket (and is used
-# for calculation).
-#
-# Do not use a TZ setting like TZ='GMT+4', which is four hours behind
-# GMT but uses the completely misleading abbreviation "GMT".
# Earlier incarnations of this package were not POSIX-compliant,
# and had lines such as
@@ -74,30 +71,31 @@ Link Etc/GMT Etc/GMT0
# way does a
# zic -l GMT-12
# so we moved the names into the Etc subdirectory.
+# Also, the time zone abbreviations are now compatible with %z.
-Zone Etc/GMT-14 14 - GMT-14 # 14 hours ahead of GMT
-Zone Etc/GMT-13 13 - GMT-13
-Zone Etc/GMT-12 12 - GMT-12
-Zone Etc/GMT-11 11 - GMT-11
-Zone Etc/GMT-10 10 - GMT-10
-Zone Etc/GMT-9 9 - GMT-9
-Zone Etc/GMT-8 8 - GMT-8
-Zone Etc/GMT-7 7 - GMT-7
-Zone Etc/GMT-6 6 - GMT-6
-Zone Etc/GMT-5 5 - GMT-5
-Zone Etc/GMT-4 4 - GMT-4
-Zone Etc/GMT-3 3 - GMT-3
-Zone Etc/GMT-2 2 - GMT-2
-Zone Etc/GMT-1 1 - GMT-1
-Zone Etc/GMT+1 -1 - GMT+1
-Zone Etc/GMT+2 -2 - GMT+2
-Zone Etc/GMT+3 -3 - GMT+3
-Zone Etc/GMT+4 -4 - GMT+4
-Zone Etc/GMT+5 -5 - GMT+5
-Zone Etc/GMT+6 -6 - GMT+6
-Zone Etc/GMT+7 -7 - GMT+7
-Zone Etc/GMT+8 -8 - GMT+8
-Zone Etc/GMT+9 -9 - GMT+9
-Zone Etc/GMT+10 -10 - GMT+10
-Zone Etc/GMT+11 -11 - GMT+11
-Zone Etc/GMT+12 -12 - GMT+12
+Zone Etc/GMT-14 14 - +14
+Zone Etc/GMT-13 13 - +13
+Zone Etc/GMT-12 12 - +12
+Zone Etc/GMT-11 11 - +11
+Zone Etc/GMT-10 10 - +10
+Zone Etc/GMT-9 9 - +09
+Zone Etc/GMT-8 8 - +08
+Zone Etc/GMT-7 7 - +07
+Zone Etc/GMT-6 6 - +06
+Zone Etc/GMT-5 5 - +05
+Zone Etc/GMT-4 4 - +04
+Zone Etc/GMT-3 3 - +03
+Zone Etc/GMT-2 2 - +02
+Zone Etc/GMT-1 1 - +01
+Zone Etc/GMT+1 -1 - -01
+Zone Etc/GMT+2 -2 - -02
+Zone Etc/GMT+3 -3 - -03
+Zone Etc/GMT+4 -4 - -04
+Zone Etc/GMT+5 -5 - -05
+Zone Etc/GMT+6 -6 - -06
+Zone Etc/GMT+7 -7 - -07
+Zone Etc/GMT+8 -8 - -08
+Zone Etc/GMT+9 -9 - -09
+Zone Etc/GMT+10 -10 - -10
+Zone Etc/GMT+11 -11 - -11
+Zone Etc/GMT+12 -12 - -12
diff --git a/openjdk/jdk/make/data/tzdata/europe b/openjdk/jdk/make/data/tzdata/europe
index 8ed7d4b..df46485 100644
--- openjdk/jdk/make/data/tzdata/europe
+++ openjdk/jdk/make/data/tzdata/europe
@@ -98,8 +98,7 @@
# 1:00 CET CEST CEMT Central Europe
# 1:00:14 SET Swedish (1879-1899)*
# 2:00 EET EEST Eastern Europe
-# 3:00 FET Further-eastern Europe (2011-2014)*
-# 3:00 MSK MSD MSM* Minsk, Moscow
+# 3:00 MSK MSD Moscow
# From Peter Ilieve (1994-12-04),
# The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -606,16 +605,33 @@ Rule E-Eur 1979 1995 - Sep lastSun 0:00 0 -
Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S
Rule E-Eur 1996 max - Oct lastSun 0:00 0 -
+
+# Daylight saving time for Russia and the Soviet Union
+#
+# The 1917-1921 decree URLs are from Alexander Belopolsky (2016-08-23).
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Russia 1917 only - Jul 1 23:00 1:00 MST # Moscow Summer Time
+#
+# Decree No. 142 (1917-12-22) http://istmat.info/node/28137
Rule Russia 1917 only - Dec 28 0:00 0 MMT # Moscow Mean Time
+#
+# Decree No. 497 (1918-05-30) http://istmat.info/node/30001
Rule Russia 1918 only - May 31 22:00 2:00 MDST # Moscow Double Summer Time
Rule Russia 1918 only - Sep 16 1:00 1:00 MST
+#
+# Decree No. 258 (1919-05-29) http://istmat.info/node/37949
Rule Russia 1919 only - May 31 23:00 2:00 MDST
-Rule Russia 1919 only - Jul 1 2:00 1:00 MSD
+#
+Rule Russia 1919 only - Jul 1 0:00u 1:00 MSD
Rule Russia 1919 only - Aug 16 0:00 0 MSK
+#
+# Decree No. 63 (1921-02-03) http://istmat.info/node/45840
Rule Russia 1921 only - Feb 14 23:00 1:00 MSD
-Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer
+#
+# Decree No. 121 (1921-03-07) http://istmat.info/node/45949
+Rule Russia 1921 only - Mar 20 23:00 2:00 +05
+#
Rule Russia 1921 only - Sep 1 0:00 1:00 MSD
Rule Russia 1921 only - Oct 1 0:00 0 -
# Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
@@ -798,8 +814,6 @@ Zone Europe/Vienna 1:05:21 - LMT 1893 Apr
# From Alexander Bokovoy (2014-10-09):
# Belarussian government decided against changing to winter time....
# http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html
-# From Paul Eggert (2014-10-08):
-# Hence Belarus can share time zone abbreviations with Moscow again.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Minsk 1:50:16 - LMT 1880
@@ -810,8 +824,7 @@ Zone Europe/Minsk 1:50:16 - LMT 1880
3:00 Russia MSK/MSD 1990
3:00 - MSK 1991 Mar 31 2:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
- 3:00 - FET 2014 Oct 26 1:00s
- 3:00 - MSK
+ 3:00 - +03
# Belgium
#
@@ -1319,7 +1332,7 @@ Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15 0:01
# http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
# says that Bersarin issued an order to use Moscow time on May 20.
# However, Moscow did not observe daylight saving in 1945, so
-# this was equivalent to CEMT (GMT+3), not GMT+4.
+# this was equivalent to UT +03, not +04.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -1510,73 +1523,84 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908
# But these events all occurred before the 1970 cutoff,
# so record only the time in Rome.
#
-# From Paul Eggert (2006-03-22):
-# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
-# F. Pollastri
-# Day-light Saving Time in Italy (2006-02-03)
-# http://toi.iriti.cnr.it/uk/ienitlt.html
-# ('FP' below), taken from an Italian National Electrotechnical Institute
-# publication. When the three sources disagree, guess who's right, as follows:
-#
-# year FP Shanks&P. (S) Whitman (W) Go with:
-# 1916 06-03 06-03 24:00 06-03 00:00 FP & W
-# 09-30 09-30 24:00 09-30 01:00 FP; guess 24:00s
-# 1917 04-01 03-31 24:00 03-31 00:00 FP & S
-# 09-30 09-29 24:00 09-30 01:00 FP & W
-# 1918 03-09 03-09 24:00 03-09 00:00 FP & S
-# 10-06 10-05 24:00 10-06 01:00 FP & W
-# 1919 03-01 03-01 24:00 03-01 00:00 FP & S
-# 10-04 10-04 24:00 10-04 01:00 FP; guess 24:00s
-# 1920 03-20 03-20 24:00 03-20 00:00 FP & S
-# 09-18 09-18 24:00 10-01 01:00 FP; guess 24:00s
-# 1944 04-02 04-03 02:00 S (see C-Eur)
-# 09-16 10-02 03:00 FP; guess 24:00s
-# 1945 09-14 09-16 24:00 FP; guess 24:00s
-# 1970 05-21 05-31 00:00 S
-# 09-20 09-27 00:00 S
+# From Michael Deckers (2016-10-24):
+# http://www.ac-ilsestante.it/MERIDIANE/ora_legale quotes a law of 1893-08-10
+# ... [translated as] "The preceding dispositions will enter into
+# force at the instant at which, according to the time specified in
+# the 1st article, the 1st of November 1893 will begin...."
+#
+# From Pierpaolo Bernardi (2016-10-20):
+# The authoritative source for time in Italy is the national metrological
+# institute, which has a summary page of historical DST data at
+# http://www.inrim.it/res/tf/ora_legale_i.shtml
+# (2016-10-24):
+# http://www.renzobaldini.it/le-ore-legali-in-italia/
+# has still different data for 1944. It divides Italy in two, as
+# there were effectively two governments at the time, north of Gothic
+# Line German controlled territory, official government RSI, and south
+# of the Gothic Line, controlled by allied armies.
+#
+# From Brian Inglis (2016-10-23):
+# Viceregal LEGISLATIVE DECREE. 14 September 1944, no. 219.
+# Restoration of Standard Time. (044U0219) (OJ 62 of 30.9.1944) ...
+# Given the R. law decreed on 1944-03-29, no. 92, by which standard time is
+# advanced to sixty minutes later starting at hour two on 1944-04-02; ...
+# Starting at hour three on the date 1944-09-17 standard time will be resumed.
+#
+# From Paul Eggert (2016-10-27):
+# Go with INRiM for DST rules, except as corrected by Inglis for 1944
+# for the Kingdom of Italy. This is consistent with Renzo Baldini.
+# Model Rome's occupation by using using C-Eur rules from 1943-09-10
+# to 1944-06-04; although Rome was an open city during this period, it
+# was effectively controlled by Germany.
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Italy 1916 only - Jun 3 0:00s 1:00 S
-Rule Italy 1916 only - Oct 1 0:00s 0 -
-Rule Italy 1917 only - Apr 1 0:00s 1:00 S
-Rule Italy 1917 only - Sep 30 0:00s 0 -
-Rule Italy 1918 only - Mar 10 0:00s 1:00 S
-Rule Italy 1918 1919 - Oct Sun>=1 0:00s 0 -
-Rule Italy 1919 only - Mar 2 0:00s 1:00 S
-Rule Italy 1920 only - Mar 21 0:00s 1:00 S
-Rule Italy 1920 only - Sep 19 0:00s 0 -
-Rule Italy 1940 only - Jun 15 0:00s 1:00 S
-Rule Italy 1944 only - Sep 17 0:00s 0 -
-Rule Italy 1945 only - Apr 2 2:00 1:00 S
-Rule Italy 1945 only - Sep 15 0:00s 0 -
-Rule Italy 1946 only - Mar 17 2:00s 1:00 S
-Rule Italy 1946 only - Oct 6 2:00s 0 -
-Rule Italy 1947 only - Mar 16 0:00s 1:00 S
-Rule Italy 1947 only - Oct 5 0:00s 0 -
-Rule Italy 1948 only - Feb 29 2:00s 1:00 S
-Rule Italy 1948 only - Oct 3 2:00s 0 -
-Rule Italy 1966 1968 - May Sun>=22 0:00 1:00 S
-Rule Italy 1966 1969 - Sep Sun>=22 0:00 0 -
-Rule Italy 1969 only - Jun 1 0:00 1:00 S
-Rule Italy 1970 only - May 31 0:00 1:00 S
-Rule Italy 1970 only - Sep lastSun 0:00 0 -
-Rule Italy 1971 1972 - May Sun>=22 0:00 1:00 S
-Rule Italy 1971 only - Sep lastSun 1:00 0 -
-Rule Italy 1972 only - Oct 1 0:00 0 -
-Rule Italy 1973 only - Jun 3 0:00 1:00 S
-Rule Italy 1973 1974 - Sep lastSun 0:00 0 -
-Rule Italy 1974 only - May 26 0:00 1:00 S
-Rule Italy 1975 only - Jun 1 0:00s 1:00 S
-Rule Italy 1975 1977 - Sep lastSun 0:00s 0 -
-Rule Italy 1976 only - May 30 0:00s 1:00 S
-Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 S
-Rule Italy 1978 only - Oct 1 0:00s 0 -
-Rule Italy 1979 only - Sep 30 0:00s 0 -
+Rule Italy 1916 only - Jun 3 24:00 1:00 S
+Rule Italy 1916 1917 - Sep 30 24:00 0 -
+Rule Italy 1917 only - Mar 31 24:00 1:00 S
+Rule Italy 1918 only - Mar 9 24:00 1:00 S
+Rule Italy 1918 only - Oct 6 24:00 0 -
+Rule Italy 1919 only - Mar 1 24:00 1:00 S
+Rule Italy 1919 only - Oct 4 24:00 0 -
+Rule Italy 1920 only - Mar 20 24:00 1:00 S
+Rule Italy 1920 only - Sep 18 24:00 0 -
+Rule Italy 1940 only - Jun 14 24:00 1:00 S
+Rule Italy 1942 only - Nov 2 2:00s 0 -
+Rule Italy 1943 only - Mar 29 2:00s 1:00 S
+Rule Italy 1943 only - Oct 4 2:00s 0 -
+Rule Italy 1944 only - Apr 2 2:00s 1:00 S
+Rule Italy 1944 only - Sep 17 2:00s 0 -
+Rule Italy 1945 only - Apr 2 2:00 1:00 S
+Rule Italy 1945 only - Sep 15 1:00 0 -
+Rule Italy 1946 only - Mar 17 2:00s 1:00 S
+Rule Italy 1946 only - Oct 6 2:00s 0 -
+Rule Italy 1947 only - Mar 16 0:00s 1:00 S
+Rule Italy 1947 only - Oct 5 0:00s 0 -
+Rule Italy 1948 only - Feb 29 2:00s 1:00 S
+Rule Italy 1948 only - Oct 3 2:00s 0 -
+Rule Italy 1966 1968 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1966 only - Sep 24 24:00 0 -
+Rule Italy 1967 1969 - Sep Sun>=22 0:00s 0 -
+Rule Italy 1969 only - Jun 1 0:00s 1:00 S
+Rule Italy 1970 only - May 31 0:00s 1:00 S
+Rule Italy 1970 only - Sep lastSun 0:00s 0 -
+Rule Italy 1971 1972 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1971 only - Sep lastSun 0:00s 0 -
+Rule Italy 1972 only - Oct 1 0:00s 0 -
+Rule Italy 1973 only - Jun 3 0:00s 1:00 S
+Rule Italy 1973 1974 - Sep lastSun 0:00s 0 -
+Rule Italy 1974 only - May 26 0:00s 1:00 S
+Rule Italy 1975 only - Jun 1 0:00s 1:00 S
+Rule Italy 1975 1977 - Sep lastSun 0:00s 0 -
+Rule Italy 1976 only - May 30 0:00s 1:00 S
+Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1978 only - Oct 1 0:00s 0 -
+Rule Italy 1979 only - Sep 30 0:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Rome 0:49:56 - LMT 1866 Sep 22
- 0:49:56 - RMT 1893 Nov 1 0:00s # Rome Mean
- 1:00 Italy CE%sT 1942 Nov 2 2:00s
- 1:00 C-Eur CE%sT 1944 Jul
+ 0:49:56 - RMT 1893 Oct 31 23:49:56 # Rome Mean
+ 1:00 Italy CE%sT 1943 Sep 10
+ 1:00 C-Eur CE%sT 1944 Jun 4
1:00 Italy CE%sT 1980
1:00 EU CE%sT
@@ -1775,6 +1799,10 @@ Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
# See Europe/Belgrade.
# Malta
+#
+# From Paul Eggert (2016-10-21):
+# Assume 1900-1972 was like Rome, overriding Shanks.
+#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Malta 1973 only - Mar 31 0:00s 1:00 S
Rule Malta 1973 only - Sep 29 0:00s 0 -
@@ -1785,8 +1813,6 @@ Rule Malta 1975 1980 - Sep Sun>=15 2:00 0 -
Rule Malta 1980 only - Mar 31 2:00 1:00 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta
- 1:00 Italy CE%sT 1942 Nov 2 2:00s
- 1:00 C-Eur CE%sT 1945 Apr 2 2:00s
1:00 Italy CE%sT 1973 Mar 31
1:00 Malta CE%sT 1981
1:00 EU CE%sT
@@ -1918,7 +1944,7 @@ Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
# Amsterdam mean time.
# The data entries before 1945 are taken from
-# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
+# http://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time
@@ -2283,7 +2309,6 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
# From Paul Eggert (2006-03-22):
-# Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
# Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
# are from Andrey A. Chernov. The rest is from Shanks & Pottenger,
# except we follow Chernov's report that 1992 DST transitions were Sat
@@ -2359,7 +2384,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
2:00 Poland CE%sT 1946
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
- 3:00 - FET 2014 Oct 26 2:00s
+ 3:00 - +03 2014 Oct 26 2:00s
2:00 - EET
@@ -2412,6 +2437,16 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
# 78 RU-SPE Saint Petersburg
# 83 RU-NEN Nenets Autonomous Okrug
+# From Paul Eggert (2016-08-23):
+# The Soviets switched to UT-based time in 1919. Decree No. 59
+# (1919-02-08) http://istmat.info/node/35567 established UT-based time
+# zones, and Decree No. 147 (1919-03-29) http://istmat.info/node/35854
+# specified a transition date of 1919-07-01, apparently at 00:00 UT.
+# No doubt only the Soviet-controlled regions switched on that date;
+# later transitions to UT-based time in other parts of Russia are
+# taken from what appear to be guesses by Shanks.
+# (Thanks to Alexander Belopolsky for pointers to the decrees.)
+
# From Stepan Golosunov (2016-03-07):
# 11. Regions-violators, 1981-1982.
# Wikipedia refers to
@@ -2453,7 +2488,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
# attributes the 1982 changes to the Act of the Council of Ministers
# of the USSR No. 126 from 18.02.1982. 1980-925.txt also adds
# Udmurtia to the list of affected territories and lists Khatangsky
-# district separately from Taymyr Autonomous Okurg. Probably erroneously.
+# district separately from Taymyr Autonomous Okrug. Probably erroneously.
#
# The affected territories are currently listed under Europe/Moscow,
# Asia/Yekaterinburg and Asia/Krasnoyarsk.
@@ -2513,7 +2548,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
Zone Europe/Moscow 2:30:17 - LMT 1880
2:30:17 - MMT 1916 Jul 3 # Moscow Mean Time
- 2:31:19 Russia %s 1919 Jul 1 2:00
+ 2:31:19 Russia %s 1919 Jul 1 0:00u
3:00 Russia %s 1921 Oct
3:00 Russia MSK/MSD 1922 Oct
2:00 - EET 1930 Jun 21
@@ -2596,22 +2631,21 @@ Zone Europe/Astrakhan 3:12:12 - LMT 1924 May
# The 1988 transition is from USSR act No. 5 (1988-01-04).
Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3
- 3:00 - TSAT 1925 Apr 6 # Tsaritsyn Time
- 3:00 - STAT 1930 Jun 21 # Stalingrad Time
- 4:00 - STAT 1961 Nov 11
- 4:00 Russia VOL%sT 1988 Mar 27 2:00s # Volgograd T
- 3:00 Russia VOL%sT 1991 Mar 31 2:00s
- 4:00 - VOLT 1992 Mar 29 2:00s
- 3:00 Russia MSK/MSD 2011 Mar 27 2:00s
- 4:00 - MSK 2014 Oct 26 2:00s
- 3:00 - MSK
+ 3:00 - +03 1930 Jun 21
+ 4:00 - +04 1961 Nov 11
+ 4:00 Russia +04/+05 1988 Mar 27 2:00s
+ 3:00 Russia +03/+04 1991 Mar 31 2:00s
+ 4:00 - +04 1992 Mar 29 2:00s
+ 3:00 Russia +03/+04 2011 Mar 27 2:00s
+ 4:00 - +04 2014 Oct 26 2:00s
+ 3:00 - +03
# From Paul Eggert (2016-03-18):
# Europe/Kirov covers:
# 43 RU-KIR Kirov Oblast
# The 1989 transition is from USSR act No. 227 (1989-03-14).
#
-Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 2:00
+Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0:00u
3:00 - +03 1930 Jun 21
4:00 Russia +04/+05 1989 Mar 26 2:00s
3:00 Russia +03/+04 1991 Mar 31 2:00s
@@ -2629,16 +2663,16 @@ Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 2:00
# Byalokoz 1919 says Samara was 3:20:20.
# The 1989 transition is from USSR act No. 227 (1989-03-14).
-Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 2:00
- 3:00 - SAMT 1930 Jun 21 # Samara Time
- 4:00 - SAMT 1935 Jan 27
- 4:00 Russia KUY%sT 1989 Mar 26 2:00s # Kuybyshev
- 3:00 Russia MSK/MSD 1991 Mar 31 2:00s
- 2:00 Russia EE%sT 1991 Sep 29 2:00s
- 3:00 - SAMT 1991 Oct 20 3:00
- 4:00 Russia SAM%sT 2010 Mar 28 2:00s
- 3:00 Russia SAM%sT 2011 Mar 27 2:00s
- 4:00 - SAMT
+Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 0:00u
+ 3:00 - +03 1930 Jun 21
+ 4:00 - +04 1935 Jan 27
+ 4:00 Russia +04/+05 1989 Mar 26 2:00s
+ 3:00 Russia +03/+04 1991 Mar 31 2:00s
+ 2:00 Russia +02/+03 1991 Sep 29 2:00s
+ 3:00 - +03 1991 Oct 20 3:00
+ 4:00 Russia +04/+05 2010 Mar 28 2:00s
+ 3:00 Russia +03/+04 2011 Mar 27 2:00s
+ 4:00 - +04
# From Paul Eggert (2016-03-18):
# Europe/Ulyanovsk covers:
@@ -2653,7 +2687,7 @@ Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 2:00
# From Matt Johnson (2016-03-09):
# http://publication.pravo.gov.ru/Document/View/0001201603090051
-Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 2:00
+Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0:00u
3:00 - +03 1930 Jun 21
4:00 Russia +04/+05 1989 Mar 26 2:00s
3:00 Russia +03/+04 1991 Mar 31 2:00s
@@ -2685,12 +2719,12 @@ Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 2:00
Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3
3:45:05 - PMT 1919 Jul 15 4:00
- 4:00 - SVET 1930 Jun 21 # Sverdlovsk Time
- 5:00 Russia SVE%sT 1991 Mar 31 2:00s
- 4:00 Russia SVE%sT 1992 Jan 19 2:00s
- 5:00 Russia YEK%sT 2011 Mar 27 2:00s
- 6:00 - YEKT 2014 Oct 26 2:00s
- 5:00 - YEKT
+ 4:00 - +04 1930 Jun 21
+ 5:00 Russia +05/+06 1991 Mar 31 2:00s
+ 4:00 Russia +04/+05 1992 Jan 19 2:00s
+ 5:00 Russia +05/+06 2011 Mar 27 2:00s
+ 6:00 - +06 2014 Oct 26 2:00s
+ 5:00 - +05
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -2700,12 +2734,12 @@ Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3
# Byalokoz 1919 says Omsk was 4:53:30.
Zone Asia/Omsk 4:53:30 - LMT 1919 Nov 14
- 5:00 - OMST 1930 Jun 21 # Omsk Time
- 6:00 Russia OMS%sT 1991 Mar 31 2:00s
- 5:00 Russia OMS%sT 1992 Jan 19 2:00s
- 6:00 Russia OMS%sT 2011 Mar 27 2:00s
- 7:00 - OMST 2014 Oct 26 2:00s
- 6:00 - OMST
+ 5:00 - +05 1930 Jun 21
+ 6:00 Russia +06/+07 1991 Mar 31 2:00s
+ 5:00 Russia +05/+06 1992 Jan 19 2:00s
+ 6:00 Russia +06/+07 2011 Mar 27 2:00s
+ 7:00 - +07 2014 Oct 26 2:00s
+ 6:00 - +06
# From Paul Eggert (2016-02-22):
# Asia/Barnaul covers:
@@ -2785,7 +2819,7 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
# Note that time belts (numbered from 2 (Moscow) to 12 according to their
# GMT/UTC offset and having too many exceptions like regions formally
# belonging to one belt but using time from another) were replaced
-# with time zones in 2011 with different numberings (there was a
+# with time zones in 2011 with different numbering (there was a
# 2-hour gap between second and third zones in 2011-2014).
# From Stepan Golosunov (2016-04-12):
@@ -2868,12 +2902,12 @@ Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1
# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6
- 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
- 7:00 Russia KRA%sT 1991 Mar 31 2:00s
- 6:00 Russia KRA%sT 1992 Jan 19 2:00s
- 7:00 Russia KRA%sT 2011 Mar 27 2:00s
- 8:00 - KRAT 2014 Oct 26 2:00s
- 7:00 - KRAT
+ 6:00 - +06 1930 Jun 21
+ 7:00 Russia +07/+08 1991 Mar 31 2:00s
+ 6:00 Russia +06/+07 1992 Jan 19 2:00s
+ 7:00 Russia +07/+08 2011 Mar 27 2:00s
+ 8:00 - +08 2014 Oct 26 2:00s
+ 7:00 - +07
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -2890,12 +2924,12 @@ Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6
Zone Asia/Irkutsk 6:57:05 - LMT 1880
6:57:05 - IMT 1920 Jan 25 # Irkutsk Mean Time
- 7:00 - IRKT 1930 Jun 21 # Irkutsk Time
- 8:00 Russia IRK%sT 1991 Mar 31 2:00s
- 7:00 Russia IRK%sT 1992 Jan 19 2:00s
- 8:00 Russia IRK%sT 2011 Mar 27 2:00s
- 9:00 - IRKT 2014 Oct 26 2:00s
- 8:00 - IRKT
+ 7:00 - +07 1930 Jun 21
+ 8:00 Russia +08/+09 1991 Mar 31 2:00s
+ 7:00 Russia +07/+08 1992 Jan 19 2:00s
+ 8:00 Russia +08/+09 2011 Mar 27 2:00s
+ 9:00 - +09 2014 Oct 26 2:00s
+ 8:00 - +08
# From Tim Parenti (2014-07-06):
@@ -2912,13 +2946,13 @@ Zone Asia/Irkutsk 6:57:05 - LMT 1880
# http://publication.pravo.gov.ru/Document/View/0001201512300107
Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAK%sT 1991 Mar 31 2:00s
- 8:00 Russia YAK%sT 1992 Jan 19 2:00s
- 9:00 Russia YAK%sT 2011 Mar 27 2:00s
- 10:00 - YAKT 2014 Oct 26 2:00s
- 8:00 - IRKT 2016 Mar 27 2:00
- 9:00 - YAKT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1991 Mar 31 2:00s
+ 8:00 Russia +08/+09 1992 Jan 19 2:00s
+ 9:00 Russia +09/+10 2011 Mar 27 2:00s
+ 10:00 - +10 2014 Oct 26 2:00s
+ 8:00 - +08 2016 Mar 27 2:00
+ 9:00 - +09
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -2958,12 +2992,12 @@ Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15
# Byalokoz 1919 says Yakutsk was 8:38:58.
Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAK%sT 1991 Mar 31 2:00s
- 8:00 Russia YAK%sT 1992 Jan 19 2:00s
- 9:00 Russia YAK%sT 2011 Mar 27 2:00s
- 10:00 - YAKT 2014 Oct 26 2:00s
- 9:00 - YAKT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1991 Mar 31 2:00s
+ 8:00 Russia +08/+09 1992 Jan 19 2:00s
+ 9:00 Russia +09/+10 2011 Mar 27 2:00s
+ 10:00 - +10 2014 Oct 26 2:00s
+ 9:00 - +09
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -2981,12 +3015,12 @@ Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15
# Go with Byalokoz.
Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15
- 9:00 - VLAT 1930 Jun 21 # Vladivostok Time
- 10:00 Russia VLA%sT 1991 Mar 31 2:00s
- 9:00 Russia VLA%sT 1992 Jan 19 2:00s
- 10:00 Russia VLA%sT 2011 Mar 27 2:00s
- 11:00 - VLAT 2014 Oct 26 2:00s
- 10:00 - VLAT
+ 9:00 - +09 1930 Jun 21
+ 10:00 Russia +10/+11 1991 Mar 31 2:00s
+ 9:00 Russia +09/+10 1992 Jan 19 2:00s
+ 10:00 Russia +10/+11 2011 Mar 27 2:00s
+ 11:00 - +11 2014 Oct 26 2:00s
+ 10:00 - +10
# From Tim Parenti (2014-07-03):
@@ -3004,14 +3038,14 @@ Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15
# This transition is no doubt wrong, but we have no better info.
Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAK%sT 1991 Mar 31 2:00s
- 8:00 Russia YAK%sT 1992 Jan 19 2:00s
- 9:00 Russia YAK%sT 2004
- 10:00 Russia VLA%sT 2011 Mar 27 2:00s
- 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725?
- 10:00 - YAKT 2014 Oct 26 2:00s
- 9:00 - YAKT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1991 Mar 31 2:00s
+ 8:00 Russia +08/+09 1992 Jan 19 2:00s
+ 9:00 Russia +09/+10 2004
+ 10:00 Russia +10/+11 2011 Mar 27 2:00s
+ 11:00 - +11 2011 Sep 13 0:00s # Decree 725?
+ 10:00 - +10 2014 Oct 26 2:00s
+ 9:00 - +09
# From Tim Parenti (2014-07-03):
@@ -3027,15 +3061,14 @@ Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15
# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
- 9:00 - JCST 1937 Oct 1
- 9:00 - JST 1945 Aug 25
- 11:00 Russia SAK%sT 1991 Mar 31 2:00s # Sakhalin T
- 10:00 Russia SAK%sT 1992 Jan 19 2:00s
- 11:00 Russia SAK%sT 1997 Mar lastSun 2:00s
- 10:00 Russia SAK%sT 2011 Mar 27 2:00s
- 11:00 - SAKT 2014 Oct 26 2:00s
- 10:00 - SAKT 2016 Mar 27 2:00s
- 11:00 - SAKT
+ 9:00 - +09 1945 Aug 25
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s # Sakhalin T
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 1997 Mar lastSun 2:00s
+ 10:00 Russia +10/+11 2011 Mar 27 2:00s
+ 11:00 - +11 2014 Oct 26 2:00s
+ 10:00 - +10 2016 Mar 27 2:00s
+ 11:00 - +11
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -3058,13 +3091,13 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
# http://publication.pravo.gov.ru/Document/View/0001201604050038
Zone Asia/Magadan 10:03:12 - LMT 1924 May 2
- 10:00 - MAGT 1930 Jun 21 # Magadan Time
- 11:00 Russia MAG%sT 1991 Mar 31 2:00s
- 10:00 Russia MAG%sT 1992 Jan 19 2:00s
- 11:00 Russia MAG%sT 2011 Mar 27 2:00s
- 12:00 - MAGT 2014 Oct 26 2:00s
- 10:00 - MAGT 2016 Apr 24 2:00s
- 11:00 - MAGT
+ 10:00 - +10 1930 Jun 21 # Magadan Time
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12 2014 Oct 26 2:00s
+ 10:00 - +10 2016 Apr 24 2:00s
+ 11:00 - +11
# From Tim Parenti (2014-07-06):
@@ -3107,17 +3140,14 @@ Zone Asia/Magadan 10:03:12 - LMT 1924 May 2
# in Russian.) In addition, Srednekolymsk appears to be a much older
# settlement and the population of Zyryanka seems to be declining.
# Go with Srednekolymsk.
-#
-# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
-# as the abbreviation. Use SRET instead.
Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
- 10:00 - MAGT 1930 Jun 21 # Magadan Time
- 11:00 Russia MAG%sT 1991 Mar 31 2:00s
- 10:00 Russia MAG%sT 1992 Jan 19 2:00s
- 11:00 Russia MAG%sT 2011 Mar 27 2:00s
- 12:00 - MAGT 2014 Oct 26 2:00s
- 11:00 - SRET # Srednekolymsk Time
+ 10:00 - +10 1930 Jun 21
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12 2014 Oct 26 2:00s
+ 11:00 - +11
# From Tim Parenti (2014-07-03):
@@ -3135,14 +3165,14 @@ Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
# UTC+12 since at least then, too.
Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAKT 1981 Apr 1
- 11:00 Russia MAG%sT 1991 Mar 31 2:00s
- 10:00 Russia MAG%sT 1992 Jan 19 2:00s
- 11:00 Russia MAG%sT 2011 Mar 27 2:00s
- 12:00 - MAGT 2011 Sep 13 0:00s # Decree 725?
- 11:00 - VLAT 2014 Oct 26 2:00s
- 10:00 - VLAT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1981 Apr 1
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12 2011 Sep 13 0:00s # Decree 725?
+ 11:00 - +11 2014 Oct 26 2:00s
+ 10:00 - +10
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -3155,12 +3185,12 @@ Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15
# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
# Asia/Petropavlovsk-Kamchatsky, but these are too long.
Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10
- 11:00 - PETT 1930 Jun 21 # P-K Time
- 12:00 Russia PET%sT 1991 Mar 31 2:00s
- 11:00 Russia PET%sT 1992 Jan 19 2:00s
- 12:00 Russia PET%sT 2010 Mar 28 2:00s
- 11:00 Russia PET%sT 2011 Mar 27 2:00s
- 12:00 - PETT
+ 11:00 - +11 1930 Jun 21
+ 12:00 Russia +12/+13 1991 Mar 31 2:00s
+ 11:00 Russia +11/+12 1992 Jan 19 2:00s
+ 12:00 Russia +12/+13 2010 Mar 28 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12
# From Tim Parenti (2014-07-03):
@@ -3168,13 +3198,13 @@ Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10
# 87 RU-CHU Chukotka Autonomous Okrug
Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2
- 12:00 - ANAT 1930 Jun 21 # Anadyr Time
- 13:00 Russia ANA%sT 1982 Apr 1 0:00s
- 12:00 Russia ANA%sT 1991 Mar 31 2:00s
- 11:00 Russia ANA%sT 1992 Jan 19 2:00s
- 12:00 Russia ANA%sT 2010 Mar 28 2:00s
- 11:00 Russia ANA%sT 2011 Mar 27 2:00s
- 12:00 - ANAT
+ 12:00 - +12 1930 Jun 21
+ 13:00 Russia +13/+14 1982 Apr 1 0:00s
+ 12:00 Russia +12/+13 1991 Mar 31 2:00s
+ 11:00 Russia +11/+12 1992 Jan 19 2:00s
+ 12:00 Russia +12/+13 2010 Mar 28 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12
# San Marino
@@ -3433,22 +3463,24 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Turkey
-# From Amar Devegowda (2007-01-03):
-# The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at:
-# http://www.timeanddate.com/worldclock/timezone.html?n=107
-# From Steffen Thorsen (2007-01-03):
-# I have been able to find press records back to 1996 which all say that
-# DST started 01:00 local time and end at 02:00 local time. I am not sure
-# what happened before that. One example for each year from 1996 to 2001:
-# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
-# From Paul Eggert (2007-01-03):
-# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+# From Kıvanç Yazan (2016-09-25):
+# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
+# no exceptions.
+# 2) 1994's lastSun was overridden with Mar 20 ...
+# Here are official papers:
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf - page 2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf - page 4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf - page 15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf - page 6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf - page 1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf - page 15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf - page 1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf - page 1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2 - for 2001
+# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2 - for 2002-2006
+# From Paul Eggert (2016-09-25):
+# Prefer the above sources to Shanks & Pottenger for time stamps after 1985.
# From Steffen Thorsen (2007-03-09):
# Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
@@ -3495,6 +3527,14 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Engineered Standard Time," said Twitter user @aysekarahasan.
# http://www.bbc.com/news/world-europe-34631326
+# From Burak AYDIN (2016-09-08):
+# Turkey will stay in Daylight Saving Time even in winter....
+# http://www.resmigazete.gov.tr/eskiler/2016/09/20160908-2.pdf
+#
+# From Paul Eggert (2016-09-07):
+# The change is permanent, so this is the new standard time in Turkey.
+# It takes effect today, which is not much notice.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Turkey 1916 only - May 1 0:00 1:00 S
Rule Turkey 1916 only - Oct 1 0:00 0 -
@@ -3549,16 +3589,16 @@ Rule Turkey 1983 only - Jul 31 0:00 1:00 S
Rule Turkey 1983 only - Oct 2 0:00 0 -
Rule Turkey 1985 only - Apr 20 0:00 1:00 S
Rule Turkey 1985 only - Sep 28 0:00 0 -
-Rule Turkey 1986 1990 - Mar lastSun 2:00s 1:00 S
-Rule Turkey 1986 1990 - Sep lastSun 2:00s 0 -
-Rule Turkey 1991 2006 - Mar lastSun 1:00s 1:00 S
-Rule Turkey 1991 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1986 1993 - Mar lastSun 1:00s 1:00 S
+Rule Turkey 1986 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1994 only - Mar 20 1:00s 1:00 S
+Rule Turkey 1995 2006 - Mar lastSun 1:00s 1:00 S
Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Istanbul 1:55:52 - LMT 1880
1:56:56 - IMT 1910 Oct # Istanbul Mean Time?
2:00 Turkey EE%sT 1978 Oct 15
- 3:00 Turkey TR%sT 1985 Apr 20 # Turkey Time
+ 3:00 Turkey +03/+04 1985 Apr 20
2:00 Turkey EE%sT 2007
2:00 EU EE%sT 2011 Mar 27 1:00u
2:00 - EET 2011 Mar 28 1:00u
@@ -3566,7 +3606,8 @@ Zone Europe/Istanbul 1:55:52 - LMT 1880
2:00 - EET 2014 Mar 31 1:00u
2:00 EU EE%sT 2015 Oct 25 1:00u
2:00 1:00 EEST 2015 Nov 8 1:00u
- 2:00 EU EE%sT
+ 2:00 EU EE%sT 2016 Sep 7
+ 3:00 - +03
Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
# Ukraine
diff --git a/openjdk/jdk/make/data/tzdata/factory b/openjdk/jdk/make/data/tzdata/factory
index 0a6041d..7d79693 100644
--- openjdk/jdk/make/data/tzdata/factory
+++ openjdk/jdk/make/data/tzdata/factory
@@ -24,9 +24,10 @@
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
-# For companies who don't want to put time zone specification in
-# their installation procedures. When users run date, they'll get the message.
-# Also useful for the "comp.sources" version.
+# For distributors who don't want to put time zone specification in
+# their installation procedures. Users that run 'date' will get the
+# time zone abbreviation "-00", indicating that the actual time zone
+# is unknown.
# Zone NAME GMTOFF RULES FORMAT
-Zone Factory 0 - "Local time zone must be set--see zic manual page"
+Zone Factory 0 - -00
diff --git a/openjdk/jdk/make/data/tzdata/leapseconds b/openjdk/jdk/make/data/tzdata/leapseconds
index a08fbc7..71d774d 100644
--- openjdk/jdk/make/data/tzdata/leapseconds
+++ openjdk/jdk/make/data/tzdata/leapseconds
@@ -79,6 +79,7 @@ Leap 2005 Dec 31 23:59:60 + S
Leap 2008 Dec 31 23:59:60 + S
Leap 2012 Jun 30 23:59:60 + S
Leap 2015 Jun 30 23:59:60 + S
+Leap 2016 Dec 31 23:59:60 + S
-# Updated through IERS Bulletin C51
-# File expires on: 28 December 2016
+# Updated through IERS Bulletin C52
+# File expires on: 28 June 2017
diff --git a/openjdk/jdk/make/data/tzdata/northamerica b/openjdk/jdk/make/data/tzdata/northamerica
index ec59510..56b089c 100644
--- openjdk/jdk/make/data/tzdata/northamerica
+++ openjdk/jdk/make/data/tzdata/northamerica
@@ -47,8 +47,32 @@
# was the result of his proposals at the Convention of Railroad Trunk Lines
# in New York City (1869-10). His 1870 proposal was based on Washington, DC,
# but in 1872-05 he moved the proposed origin to Greenwich.
-# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
-# and the most of the country soon followed suit.
+
+# From Paul Eggert (2016-09-21):
+# Dowd's proposal left many details unresolved, such as where to draw
+# lines between time zones. The key individual who made time zones
+# work in the US was William Frederick Allen - railway engineer,
+# managing editor of the Travelers' Guide, and secretary of the
+# General Time Convention, a railway standardization group. Allen
+# spent months in dialogs with scientific and railway leaders,
+# developed a workable plan to institute time zones, and presented it
+# to the General Time Convention on 1883-04-11, saying that his plan
+# meant "local time would be practically abolished" - a plus for
+# railway scheduling. By the next convention on 1883-10-11 nearly all
+# railroads had agreed and it took effect on 1883-11-18 at 12:00.
+# That Sunday was called the "day of two noons", as the eastern parts
+# of the new zones observed noon twice. Allen witnessed the
+# transition in New York City, writing:
+#
+# I heard the bells of St. Paul's strike on the old time. Four
+# minutes later, obedient to the electrical signal from the Naval
+# Observatory ... the time-ball made its rapid descent, the chimes
+# of old Trinity rang twelve measured strokes, and local time was
+# abandoned, probably forever.
+#
+# Most of the US soon followed suit. See:
+# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56.
+# http://dx.doi.org/10.2307/3105430
# From Paul Eggert (2005-04-16):
# That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
@@ -436,11 +460,42 @@ Zone America/Denver -6:59:56 - LMT 1883 Nov 18 12:00:04
# north of the Salmon River, and the towns of Burgdorf and Warren),
# Nevada (except West Wendover), Oregon (except the northern 3/4 of
# Malheur county), and Washington
+
+# From Paul Eggert (2016-08-20):
+# In early February 1948, in response to California's electricity shortage,
+# PG&E changed power frequency from 60 to 59.5 Hz during daylight hours,
+# causing electric clocks to lose six minutes per day. (This did not change
+# legal time, and is not part of the data here.) See:
+# Ross SA. An energy crisis from the past: Northern California in 1948.
+# Working Paper No. 8, Institute of Governmental Studies, UC Berkeley,
+# 1973-11. http://escholarship.org/uc/item/8x22k30c
+#
+# In another measure to save electricity, DST was instituted from 1948-03-14
+# at 02:01 to 1949-01-16 at 02:00, with the governor having the option to move
+# the fallback transition earlier. See pages 3-4 of:
+# http://clerk.assembly.ca.gov/sites/clerk.assembly.ca.gov/files/archive/Statutes/1948/48Vol1_Chapters.pdf
+#
+# In response:
+#
+# Governor Warren received a torrent of objecting mail, and it is not too much
+# to speculate that the objections to Daylight Saving Time were one important
+# factor in the defeat of the Dewey-Warren Presidential ticket in California.
+# -- Ross, p 25
+#
+# On December 8 the governor exercised the option, setting the date to January 1
+# (LA Times 1948-12-09). The transition time was 02:00 (LA Times 1949-01-01).
+#
+# Despite the controversy, in 1949 California voters approved Proposition 12,
+# which established DST from April's last Sunday at 01:00 until September's
+# last Sunday at 02:00. This was amended by 1962's Proposition 6, which changed
+# the fall-back date to October's last Sunday. See:
+# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1501&context=ca_ballot_props
+# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1636&context=ca_ballot_props
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
-Rule CA 1948 only - Mar 14 2:00 1:00 D
+Rule CA 1948 only - Mar 14 2:01 1:00 D
Rule CA 1949 only - Jan 1 2:00 0 S
-Rule CA 1950 1966 - Apr lastSun 2:00 1:00 D
+Rule CA 1950 1966 - Apr lastSun 1:00 1:00 D
Rule CA 1950 1961 - Sep lastSun 2:00 0 S
Rule CA 1962 1966 - Oct lastSun 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -3304,7 +3359,7 @@ Zone America/Miquelon -3:44:40 - LMT 1911 May 15 # St Pierre
# indicating that the normal ET rules are followed.
#
# From Paul Eggert (2014-08-19):
-# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round. See:
+# The 2014-08-13 Cabinet meeting decided to stay on UT -04 year-round. See:
# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
# Model this as a switch from EST/EDT to AST ...
# From Chris Walton (2014-11-04):
diff --git a/openjdk/jdk/make/data/tzdata/southamerica b/openjdk/jdk/make/data/tzdata/southamerica
index 08c89ca..bbc0a95 100644
--- openjdk/jdk/make/data/tzdata/southamerica
+++ openjdk/jdk/make/data/tzdata/southamerica
@@ -433,9 +433,9 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
# stuck on Summer daylight savings time even though the summer is over.
# From Paul Eggert (2013-09-05):
-# Perhaps San Luis operates on the legal fiction that it is at UTC-4
+# Perhaps San Luis operates on the legal fiction that it is at -04
# with perpetual summer time, but ordinary usage typically seems to
-# just say it's at UTC-3; see, for example,
+# just say it's at -03; see, for example,
# http://es.wikipedia.org/wiki/Hora_oficial_argentina
# We've documented similar situations as being plain changes to
# standard time, so let's do that here too. This does not change UTC
diff --git a/openjdk/jdk/make/data/tzdata/zone.tab b/openjdk/jdk/make/data/tzdata/zone.tab
index 5649691..2de07ef 100644
--- openjdk/jdk/make/data/tzdata/zone.tab
+++ openjdk/jdk/make/data/tzdata/zone.tab
@@ -175,7 +175,8 @@ CU +2308-08222 America/Havana
CV +1455-02331 Atlantic/Cape_Verde
CW +1211-06900 America/Curacao
CX -1025+10543 Indian/Christmas
-CY +3510+03322 Asia/Nicosia
+CY +3510+03322 Asia/Nicosia Cyprus (most areas)
+CY +3507+03357 Asia/Famagusta Northern Cyprus
CZ +5005+01426 Europe/Prague
DE +5230+01322 Europe/Berlin Germany (most areas)
DE +4742+00841 Europe/Busingen Busingen
@@ -284,7 +285,7 @@ MH +0709+17112 Pacific/Majuro Marshall Islands (most areas)
MH +0905+16720 Pacific/Kwajalein Kwajalein
MK +4159+02126 Europe/Skopje
ML +1239-00800 Africa/Bamako
-MM +1647+09610 Asia/Rangoon
+MM +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas)
MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
diff --git a/openjdk/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java b/openjdk/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
index f63441b..94b5429 100644
--- openjdk/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
+++ openjdk/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
@@ -121,7 +121,7 @@ class _AppMenuBarHandler {
}
// grab the pointer to the CMenuBar, and retain it in native
- nativeSetDefaultMenuBar(((CMenuBar)peer).getModel());
+ ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar);
}
void setAboutMenuItemVisible(final boolean present) {
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
index da53c30..d21de34 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,29 +26,28 @@
package sun.lwawt.macosx;
import java.awt.CheckboxMenuItem;
-import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.peer.CheckboxMenuItemPeer;
import sun.awt.SunToolkit;
public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer {
- boolean fAutoToggle = true;
- boolean fIsIndeterminate = false;
+ volatile boolean fAutoToggle = true;
+ volatile boolean fIsIndeterminate = false;
private native void nativeSetState(long modelPtr, boolean state);
private native void nativeSetIsCheckbox(long modelPtr);
- CCheckboxMenuItem(CheckboxMenuItem target) {
+ CCheckboxMenuItem(final CheckboxMenuItem target) {
super(target);
- nativeSetIsCheckbox(getModel());
+ execute(this::nativeSetIsCheckbox);
setState(target.getState());
}
// MenuItemPeer implementation
@Override
- public void setState(boolean state) {
- nativeSetState(getModel(), state);
+ public void setState(final boolean state) {
+ execute(ptr -> nativeSetState(ptr, state));
}
public void handleAction(final boolean state) {
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
index f218c90..11f05b5 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
@@ -91,7 +91,7 @@ public class CEmbeddedFrame extends EmbeddedFrame {
int x = (int)pluginX;
int y = (int)pluginY;
- responder.handleScrollEvent(x, y, modifierFlags, deltaX, deltaY);
+ responder.handleScrollEvent(x, y, modifierFlags, deltaX, deltaY, NSEvent.SCROLL_PHASE_UNSUPPORTED);
}
public void handleKeyEvent(int eventType, int modifierFlags, String characters,
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
index cec76f5..f69ad20 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
@@ -23,7 +23,6 @@
* questions.
*/
-
package sun.lwawt.macosx;
/**
@@ -34,6 +33,7 @@ public class CFRetainedResource {
private static native void nativeCFRelease(final long ptr, final boolean disposeOnAppKitThread);
private final boolean disposeOnAppKitThread;
+ // TODO this pointer should be private and accessed via CFNativeAction class
protected volatile long ptr;
/**
@@ -70,8 +70,72 @@ public class CFRetainedResource {
nativeCFRelease(oldPtr, disposeOnAppKitThread); // perform outside of the synchronized block
}
+ /**
+ * The interface which allows to execute some native operations with
+ * assumption that the native pointer will be valid till the end.
+ */
+ public interface CFNativeAction {
+
+ /**
+ * The native operation should be called from this method.
+ *
+ * @param ptr the pointer to the native data
+ */
+ void run(long ptr);
+ }
+
+ /**
+ * The interface which allows to execute some native operations and get a
+ * result with assumption that the native pointer will be valid till the
+ * end.
+ */
+ interface CFNativeActionGet {
+
+ /**
+ * The native operation should be called from this method.
+ *
+ * @param ptr the pointer to the native data
+ * @return result of the native operation
+ */
+ long run(long ptr);
+ }
+
+ /**
+ * This is utility method which should be used instead of the direct access
+ * to the {@link #ptr}, because this method guaranteed that the pointer will
+ * not be zero and will be valid till the end of the operation.It is highly
+ * recomended to not use any external lock in action. If the current
+ * {@link #ptr} is {@code 0} then action will be ignored.
+ *
+ * @param action The native operation
+ */
+ public final synchronized void execute(final CFNativeAction action) {
+ if (ptr != 0) {
+ action.run(ptr);
+ }
+ }
+
+ /**
+ * This is utility method which should be used instead of the direct access
+ * to the {@link #ptr}, because this method guaranteed that the pointer will
+ * not be zero and will be valid till the end of the operation. It is highly
+ * recomended to not use any external lock in action. If the current
+ * {@link #ptr} is {@code 0} then action will be ignored and {@code} is
+ * returned.
+ *
+ * @param action the native operation
+ * @return result of the native operation, usually the native pointer to
+ * some other data
+ */
+ final synchronized long executeGet(final CFNativeActionGet action) {
+ if (ptr != 0) {
+ return action.run(ptr);
+ }
+ return 0;
+ }
+
@Override
- protected void finalize() throws Throwable {
+ protected final void finalize() throws Throwable {
dispose();
}
}
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java
index 9e1499b..4f2fc96 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
package sun.lwawt.macosx;
-import java.awt.*;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
@@ -37,7 +39,7 @@ public class CMenu extends CMenuItem implements MenuPeer {
// This way we avoiding invocation of the setters twice
@Override
- protected void initialize(MenuItem target) {
+ protected final void initialize(MenuItem target) {
setLabel(target.getLabel());
setEnabled(target.isEnabled());
}
@@ -57,52 +59,50 @@ public class CMenu extends CMenuItem implements MenuPeer {
}
@Override
- protected long createModel() {
+ long createModel() {
CMenuComponent parent = (CMenuComponent)
LWCToolkit.targetToPeer(getTarget().getParent());
- if (parent instanceof CMenu ||
- parent instanceof CPopupMenu)
- {
- return nativeCreateSubMenu(parent.getModel());
- } else if (parent instanceof CMenuBar) {
+ if (parent instanceof CMenu) {
+ return parent.executeGet(this::nativeCreateSubMenu);
+ }
+ if (parent instanceof CMenuBar) {
MenuBar parentContainer = (MenuBar)getTarget().getParent();
boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
- return nativeCreateMenu(parent.getModel(),
- isHelpMenu, insertionLocation);
- } else {
- throw new InternalError("Parent must be CMenu or CMenuBar");
+ return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
+ insertionLocation));
}
+ throw new InternalError("Parent must be CMenu or CMenuBar");
}
@Override
- public void addItem(MenuItem item) {
+ public final void addItem(MenuItem item) {
// Nothing to do here -- we added it when we created the
// menu item's peer.
}
@Override
- public void delItem(int index) {
- nativeDeleteItem(getModel(), index);
+ public final void delItem(final int index) {
+ execute(ptr -> nativeDeleteItem(ptr, index));
}
@Override
- public void setLabel(String label) {
- nativeSetMenuTitle(getModel(), label);
+ public final void setLabel(final String label) {
+ execute(ptr->nativeSetMenuTitle(ptr, label));
super.setLabel(label);
}
// Note that addSeparator is never called directly from java.awt.Menu,
// though it is required in the MenuPeer interface.
@Override
- public void addSeparator() {
- nativeAddSeparator(getModel());
+ public final void addSeparator() {
+ execute(this::nativeAddSeparator);
}
// Used by ScreenMenuBar to get to the native menu for event handling.
- public long getNativeMenu() {
- return nativeGetNSMenu(getModel());
+ public final long getNativeMenu() {
+ return executeGet(this::nativeGetNSMenu);
}
private native long nativeCreateMenu(long parentMenuPtr,
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java
index 0bed715..6e80370 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,9 @@ import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.peer.MenuBarPeer;
-public class CMenuBar extends CMenuComponent implements MenuBarPeer {
+import sun.awt.AWTAccessor;
+
+public final class CMenuBar extends CMenuComponent implements MenuBarPeer {
private int nextInsertionIndex = -1;
@@ -38,15 +40,16 @@ public class CMenuBar extends CMenuComponent implements MenuBarPeer {
}
@Override
- protected long createModel() {
+ long createModel() {
return nativeCreateMenuBar();
}
@Override
- public void addHelpMenu(Menu m) {
- CMenu cMenu = (CMenu)m.getPeer();
- nativeSetHelpMenu(getModel(), cMenu.getModel());
- }
+ public void addHelpMenu(final Menu m) {
+ final CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m);
+ execute(parentPtr -> cMenu.execute(
+ menuPtr -> nativeSetHelpMenu(parentPtr, menuPtr)));
+ }
public int getNextInsertionIndex() {
return nextInsertionIndex;
@@ -63,8 +66,8 @@ public class CMenuBar extends CMenuComponent implements MenuBarPeer {
}
@Override
- public void delMenu(int index) {
- nativeDelMenu(getModel(), index);
+ public void delMenu(final int index) {
+ execute(ptr -> nativeDelMenu(ptr, index));
}
private native long nativeCreateMenuBar();
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
index 2dbc923..6100916 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,36 +29,32 @@ import java.awt.Font;
import java.awt.MenuComponent;
import java.awt.peer.MenuComponentPeer;
-public abstract class CMenuComponent implements MenuComponentPeer {
+abstract class CMenuComponent extends CFRetainedResource
+ implements MenuComponentPeer {
- private MenuComponent target;
- private long modelPtr;
+ private final MenuComponent target;
- CMenuComponent(MenuComponent target) {
+ CMenuComponent(final MenuComponent target) {
+ super(0, true);
this.target = target;
- this.modelPtr = createModel();
+ setPtr(createModel());
}
- MenuComponent getTarget() {
+ final MenuComponent getTarget() {
return target;
}
- public long getModel() {
- return modelPtr;
- }
-
- protected abstract long createModel();
+ abstract long createModel();
- public void dispose() {
+ @Override
+ public final void dispose() {
+ super.dispose();
LWCToolkit.targetDisposedPeer(target, this);
- nativeDispose(modelPtr);
- target = null;
}
- private native void nativeDispose(long modelPtr);
-
// 1.5 peer method
- public void setFont(Font f) {
+ @Override
+ public final void setFont(final Font f) {
// no-op, as we don't currently support menu fonts
// c.f. radar 4032912
}
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java
index dbe6a8c..01427db 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,16 +25,17 @@
package sun.lwawt.macosx;
-import sun.awt.SunToolkit;
-import sun.lwawt.LWToolkit;
-
-import java.awt.MenuContainer;
import java.awt.MenuItem;
import java.awt.MenuShortcut;
-import java.awt.event.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
import java.awt.peer.MenuItemPeer;
import java.util.concurrent.atomic.AtomicBoolean;
+import sun.awt.SunToolkit;
+import sun.lwawt.LWToolkit;
+
public class CMenuItem extends CMenuComponent implements MenuItemPeer {
private final AtomicBoolean enabled = new AtomicBoolean(true);
@@ -58,9 +59,9 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
}
@Override
- protected long createModel() {
+ long createModel() {
CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
- return nativeCreate(parent.getModel(), isSeparator());
+ return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
}
public void setLabel(String label, char keyChar, int keyCode, int modifiers) {
@@ -90,7 +91,12 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
keyChar = 0;
}
- nativeSetLabel(getModel(), label, keyChar, keyCode, keyMask);
+ final String finalLabel = label;
+ final char finalKeyChar = keyChar;
+ final int finalKeyCode = keyCode;
+ final int finalKeyMask = keyMask;
+ execute(ptr -> nativeSetLabel(ptr, finalLabel, finalKeyChar,
+ finalKeyCode, finalKeyMask));
}
@Override
@@ -105,16 +111,16 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
* There isn't a need to expose this except in a instanceof because
* it isn't defined in the peer api.
*/
- public void setImage(java.awt.Image img) {
+ public final void setImage(final java.awt.Image img) {
CImage cimg = CImage.getCreator().createFromImage(img);
- nativeSetImage(getModel(), cimg == null ? 0L : cimg.ptr);
+ execute(ptr -> nativeSetImage(ptr, cimg == null ? 0L : cimg.ptr));
}
/**
* New API for tooltips
*/
- public void setToolTipText(String text) {
- nativeSetTooltip(getModel(), text);
+ public final void setToolTipText(final String text) {
+ execute(ptr -> nativeSetTooltip(ptr, text));
}
// @Override
@@ -138,7 +144,8 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
b &= ((CMenuItem) parent).isEnabled();
}
if (enabled.compareAndSet(!b, b)) {
- nativeSetEnabled(getModel(), b);
+ final boolean finalB = b;
+ execute(ptr->nativeSetEnabled(ptr, finalB));
}
}
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
index 804d2d0..15c377f 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
@@ -44,6 +44,8 @@ final class CPlatformResponder {
private final PlatformEventNotifier eventNotifier;
private final boolean isNpapiCallback;
private int lastKeyPressCode = KeyEvent.VK_UNDEFINED;
+ private final DeltaAccumulator deltaAccumulatorX = new DeltaAccumulator();
+ private final DeltaAccumulator deltaAccumulatorY = new DeltaAccumulator();
CPlatformResponder(final PlatformEventNotifier eventNotifier,
final boolean isNpapiCallback) {
@@ -90,37 +92,38 @@ final class CPlatformResponder {
* Handles scroll events.
*/
void handleScrollEvent(final int x, final int y, final int modifierFlags,
- final double deltaX, final double deltaY) {
+ final double deltaX, final double deltaY,
+ final int scrollPhase) {
final int buttonNumber = CocoaConstants.kCGMouseButtonCenter;
int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber,
modifierFlags);
final boolean isShift = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0;
+ int roundDeltaX = deltaAccumulatorX.getRoundedDelta(deltaX, scrollPhase);
+ int roundDeltaY = deltaAccumulatorY.getRoundedDelta(deltaY, scrollPhase);
+
// Vertical scroll.
- if (!isShift && deltaY != 0.0) {
- dispatchScrollEvent(x, y, jmodifiers, deltaY);
+ if (!isShift && (deltaY != 0.0 || roundDeltaY != 0)) {
+ dispatchScrollEvent(x, y, jmodifiers, roundDeltaY, deltaY);
}
// Horizontal scroll or shirt+vertical scroll.
final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX;
- if (delta != 0.0) {
+ final int roundDelta = isShift && roundDeltaY != 0 ? roundDeltaY : roundDeltaX;
+ if (delta != 0.0 || roundDelta != 0) {
jmodifiers |= InputEvent.SHIFT_DOWN_MASK;
- dispatchScrollEvent(x, y, jmodifiers, delta);
+ dispatchScrollEvent(x, y, jmodifiers, roundDelta, delta);
}
}
private void dispatchScrollEvent(final int x, final int y,
- final int modifiers, final double delta) {
+ final int modifiers,
+ final int roundDelta, final double delta) {
final long when = System.currentTimeMillis();
final int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL;
final int scrollAmount = 1;
- int wheelRotation = (int) delta;
- int signum = (int) Math.signum(delta);
- if (signum * delta < 1) {
- wheelRotation = signum;
- }
// invert the wheelRotation for the peer
eventNotifier.notifyMouseWheelEvent(when, x, y, modifiers, scrollType,
- scrollAmount, -wheelRotation, -delta, null);
+ scrollAmount, -roundDelta, -delta, null);
}
/**
@@ -256,4 +259,46 @@ final class CPlatformResponder {
void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) {
eventNotifier.notifyActivation(gained, opposite);
}
+
+ static class DeltaAccumulator {
+
+ static final double MIN_THRESHOLD = 0.1;
+ static final double MAX_THRESHOLD = 0.5;
+ double accumulatedDelta;
+
+ int getRoundedDelta(double delta, int scrollPhase) {
+
+ int roundDelta = (int) Math.round(delta);
+
+ if (scrollPhase == NSEvent.SCROLL_PHASE_UNSUPPORTED) { // mouse wheel
+ if (roundDelta == 0 && delta != 0) {
+ roundDelta = delta > 0 ? 1 : -1;
+ }
+ } else { // trackpad
+ boolean begin = scrollPhase == NSEvent.SCROLL_PHASE_BEGAN;
+ boolean end = scrollPhase == NSEvent.SCROLL_MASK_PHASE_ENDED
+ || scrollPhase == NSEvent.SCROLL_MASK_PHASE_CANCELLED;
+
+ if (begin) {
+ accumulatedDelta = 0;
+ }
+
+ accumulatedDelta += delta;
+
+ double absAccumulatedDelta = Math.abs(accumulatedDelta);
+ if (absAccumulatedDelta > MAX_THRESHOLD) {
+ roundDelta = (int) Math.round(accumulatedDelta);
+ accumulatedDelta -= roundDelta;
+ }
+
+ if (end) {
+ if (roundDelta == 0 && absAccumulatedDelta > MIN_THRESHOLD) {
+ roundDelta = accumulatedDelta > 0 ? 1 : -1;
+ }
+ }
+ }
+
+ return roundDelta;
+ }
+ }
}
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
index 3c2cd23..9d1acaf 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
@@ -192,7 +192,8 @@ public class CPlatformView extends CFRetainedResource {
if (event.getType() == CocoaConstants.NSScrollWheel) {
responder.handleScrollEvent(x, y, event.getModifierFlags(),
- event.getScrollDeltaX(), event.getScrollDeltaY());
+ event.getScrollDeltaX(), event.getScrollDeltaY(),
+ event.getScrollPhase());
} else {
responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(),
event.getClickCount(), x, y, event.getAbsX(), event.getAbsY());
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
index cdaae47..640a0de 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
@@ -419,7 +419,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
final long nsWindowPtr = getNSWindowPtr();
CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb);
if (mbPeer != null) {
- nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel());
+ mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr));
} else {
nativeSetNSWindowMenuBar(nsWindowPtr, 0);
}
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
index 67ddf91..b73f67a 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,18 +25,20 @@
package sun.lwawt.macosx;
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Event;
+import java.awt.Point;
+import java.awt.PopupMenu;
import java.awt.peer.PopupMenuPeer;
-import sun.lwawt.LWWindowPeer;
+final class CPopupMenu extends CMenu implements PopupMenuPeer {
-public class CPopupMenu extends CMenu implements PopupMenuPeer {
CPopupMenu(PopupMenu target) {
super(target);
}
@Override
- protected long createModel() {
+ long createModel() {
return nativeCreatePopupMenu();
}
@@ -50,7 +52,7 @@ public class CPopupMenu extends CMenu implements PopupMenuPeer {
Point loc = origin.getLocationOnScreen();
e.x += loc.x;
e.y += loc.y;
- nativeShowPopupMenu(getModel(), e.x, e.y);
+ execute(ptr -> nativeShowPopupMenu(ptr, e.x, e.y));
}
}
}
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
index 8e2a18f..ff1648d 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,7 +104,10 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
return 0L;
}
}
- return checkAndCreatePopupPeer().getModel();
+ // This method is executed on Appkit, so if ptr is not zero means that,
+ // it is still not deallocated(even if we call NSApp postRunnableEvent)
+ // and sent CFRelease to the native queue
+ return checkAndCreatePopupPeer().ptr;
}
/**
diff --git a/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/NSEvent.java b/openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/NSEvent.java
index d30a39c..eccc257 100644
--- openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/NSEvent.java
+++ openjdk/jdk/src/macosx/classes/sun/lwawt/macosx/NSEvent.java
@@ -32,6 +32,13 @@ import java.awt.event.*;
* JDK functionality.
*/
final class NSEvent {
+
+ static final int SCROLL_PHASE_UNSUPPORTED = 1;
+ static final int SCROLL_PHASE_BEGAN = 2;
+ static final int SCROLL_PHASE_CONTINUED = 3;
+ static final int SCROLL_MASK_PHASE_CANCELLED = 4;
+ static final int SCROLL_MASK_PHASE_ENDED = 5;
+
private int type;
private int modifierFlags;
@@ -42,6 +49,7 @@ final class NSEvent {
private int y;
private double scrollDeltaY;
private double scrollDeltaX;
+ private int scrollPhase;
private int absX;
private int absY;
@@ -62,7 +70,7 @@ final class NSEvent {
// Called from native
NSEvent(int type, int modifierFlags, int clickCount, int buttonNumber,
int x, int y, int absX, int absY,
- double scrollDeltaY, double scrollDeltaX) {
+ double scrollDeltaY, double scrollDeltaX, int scrollPhase) {
this.type = type;
this.modifierFlags = modifierFlags;
this.clickCount = clickCount;
@@ -73,6 +81,7 @@ final class NSEvent {
this.absY = absY;
this.scrollDeltaY = scrollDeltaY;
this.scrollDeltaX = scrollDeltaX;
+ this.scrollPhase = scrollPhase;
}
int getType() {
@@ -107,6 +116,10 @@ final class NSEvent {
return scrollDeltaX;
}
+ int getScrollPhase() {
+ return scrollPhase;
+ }
+
int getAbsX() {
return absX;
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m b/openjdk/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m
index d12908c..8b0d576 100644
--- openjdk/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m
+++ openjdk/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -103,8 +103,6 @@ JNF_COCOA_ENTER(env);
CALayer *windowLayer = jlong_to_ptr(windowLayerPtr);
surfaceLayers = [[AWTSurfaceLayers alloc] initWithWindowLayer: windowLayer];
- CFRetain(surfaceLayers);
- [surfaceLayers release];
}];
JNF_COCOA_EXIT(env);
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/AWTView.m b/openjdk/jdk/src/macosx/native/sun/awt/AWTView.m
index ec33dd9..35c9440 100644
--- openjdk/jdk/src/macosx/native/sun/awt/AWTView.m
+++ openjdk/jdk/src/macosx/native/sun/awt/AWTView.m
@@ -114,9 +114,9 @@ AWT_ASSERT_APPKIT_THREAD;
remoteLayer.parentLayer = parentLayer;
remoteLayer.remoteLayer = NULL;
remoteLayer.jrsRemoteLayer = [remoteLayer createRemoteLayerBoundTo:JRSRemotePort];
- CFRetain(remoteLayer); // REMIND
+ [remoteLayer retain]; // REMIND
remoteLayer.frame = CGRectMake(0, 0, 720, 500); // REMIND
- CFRetain(remoteLayer.jrsRemoteLayer); // REMIND
+ [remoteLayer.jrsRemoteLayer retain]; // REMIND
int layerID = [remoteLayer.jrsRemoteLayer layerID];
NSLog(@"layer id to send = %d", layerID);
sendLayerID(layerID);
@@ -386,7 +386,7 @@ AWT_ASSERT_APPKIT_THREAD;
}
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
- static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+ static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
[event type],
[event modifierFlags],
@@ -395,7 +395,8 @@ AWT_ASSERT_APPKIT_THREAD;
(jint)localPoint.x, (jint)localPoint.y,
(jint)absP.x, (jint)absP.y,
[event deltaY],
- [event deltaX]);
+ [event deltaX],
+ [AWTToolkit scrollStateWithEvent: event]);
if (jEvent == nil) {
// Unable to create event by some reason.
return;
@@ -1340,12 +1341,9 @@ JNF_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
CALayer *windowLayer = jlong_to_ptr(windowLayerPtr);
- AWTView *view = [[AWTView alloc] initWithRect:rect
- platformView:cPlatformView
- windowLayer:windowLayer];
- CFRetain(view);
- [view release]; // GC
- newView = view;
+ newView = [[AWTView alloc] initWithRect:rect
+ platformView:cPlatformView
+ windowLayer:windowLayer];
}];
JNF_COCOA_EXIT(env);
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/AWTWindow.m b/openjdk/jdk/src/macosx/native/sun/awt/AWTWindow.m
index 1194ad8..b84f0ec 100644
--- openjdk/jdk/src/macosx/native/sun/awt/AWTWindow.m
+++ openjdk/jdk/src/macosx/native/sun/awt/AWTWindow.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -800,6 +800,18 @@ AWT_ASSERT_APPKIT_THREAD;
- (void)sendEvent:(NSEvent *)event {
if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
+ // Move parent windows to front and make sure that a child window is displayed
+ // in front of its nearest parent.
+ if (self.ownerWindow != nil) {
+ JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
+ jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
+ if (platformWindow != NULL) {
+ static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
+ JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
+ (*env)->DeleteLocalRef(env, platformWindow);
+ }
+ }
+ [self orderChildWindows:YES];
NSPoint p = [NSEvent mouseLocation];
NSRect frame = [self.nsWindow frame];
@@ -904,7 +916,7 @@ JNF_COCOA_ENTER(env);
contentView:contentView];
// the window is released is CPlatformWindow.nativeDispose()
- if (window) CFRetain(window.nsWindow);
+ if (window) [window.nsWindow retain];
}];
JNF_COCOA_EXIT(env);
@@ -1100,6 +1112,16 @@ JNF_COCOA_ENTER(env);
NSWindow *nsWindow = OBJC(windowPtr);
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
[nsWindow orderBack:nil];
+ // Order parent windows
+ AWTWindow *awtWindow = (AWTWindow*)[nsWindow delegate];
+ while (awtWindow.ownerWindow != nil) {
+ awtWindow = awtWindow.ownerWindow;
+ if ([AWTWindow isJavaPlatformWindowVisible:awtWindow.nsWindow]) {
+ [awtWindow.nsWindow orderBack:nil];
+ }
+ }
+ // Order child windows
+ [(AWTWindow*)[nsWindow delegate] orderChildWindows:NO];
}];
JNF_COCOA_EXIT(env);
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m b/openjdk/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m
index 8195575..dcad651 100644
--- openjdk/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m
+++ openjdk/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -255,8 +255,6 @@ AWT_ASSERT_APPKIT_THREAD;
[super dealloc];
}
-//- (void)finalize { [super finalize]; } // GC
-
#pragma mark Callbacks from AppKit
@@ -623,8 +621,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeGetDockIc
JNF_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- image = [ApplicationDelegate _dockIconImage];
- CFRetain(image);
+ image = [[ApplicationDelegate _dockIconImage] retain];
}];
JNF_COCOA_EXIT(env);
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CClipboard.m b/openjdk/jdk/src/macosx/native/sun/awt/CClipboard.m
index dde4ed8..543ed20 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CClipboard.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CClipboard.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,6 @@ static CClipboard *sClipboard = nil;
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
- (NSData *)data {
return fData;
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CDesktopPeer.m b/openjdk/jdk/src/macosx/native/sun/awt/CDesktopPeer.m
index ef9bdb6..ae44084 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CDesktopPeer.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CDesktopPeer.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@ JNF_COCOA_ENTER(env);
LSApplicationParameters params = {0, flags, NULL, NULL, NULL, NULL, NULL};
status = LSOpenURLsWithRole((CFArrayRef)[NSArray arrayWithObject:url], kLSRolesAll, NULL, ¶ms, NULL, 0);
- CFRelease(url);
+ [url release];
JNF_COCOA_EXIT(env);
return status;
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CDragSource.m b/openjdk/jdk/src/macosx/native/sun/awt/CDragSource.m
index da67762..1f6d9b0 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CDragSource.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CDragSource.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -193,7 +193,7 @@ static BOOL sNeedsEnter;
fFormatMap = NULL;
}
- CFRelease(self); // GC
+ [self release];
}
- (void)dealloc
@@ -209,8 +209,6 @@ static BOOL sNeedsEnter;
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
-
// Appropriated from Windows' awt_DataTransferer.cpp:
//
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m b/openjdk/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m
index e1a7ab3..890c51c 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -67,10 +67,6 @@ JNF_COCOA_ENTER(env);
}];
JNF_COCOA_EXIT(env);
- if (dragSource) {
- CFRetain(dragSource); // GC
- [dragSource release];
- }
return ptr_to_jlong(dragSource);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CDropTarget.m b/openjdk/jdk/src/macosx/native/sun/awt/CDropTarget.m
index 7c2c0e1..0b3b184 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CDropTarget.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CDropTarget.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -171,7 +171,7 @@ extern JNFClassInfo jc_CDropTargetContextPeer;
fDropTargetContextPeer = NULL;
}
- CFRelease(self);
+ [self release];
}
- (void)dealloc
@@ -187,7 +187,6 @@ extern JNFClassInfo jc_CDropTargetContextPeer;
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
- (NSInteger) getDraggingSequenceNumber
{
@@ -724,10 +723,6 @@ JNF_COCOA_ENTER(env);
dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent peer:jpeer control:controlObj];
JNF_COCOA_EXIT(env);
- if (dropTarget) {
- CFRetain(dropTarget); // GC
- [dropTarget release];
- }
return ptr_to_jlong(dropTarget);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CFileDialog.m b/openjdk/jdk/src/macosx/native/sun/awt/CFileDialog.m
index 7dc8202..ee75309 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CFileDialog.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CFileDialog.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -88,7 +88,6 @@ canChooseDirectories:(BOOL)inChooseDirectories
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
- (void)safeSaveOrLoad {
NSSavePanel *thePanel = nil;
@@ -168,9 +167,9 @@ canChooseDirectories:(BOOL)inChooseDirectories
}
// ask the file filter up in Java
- CFStringRef filePath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle);
- BOOL shouldEnableFile = [self askFilenameFilter:(NSString *)filePath];
- CFRelease(filePath);
+ NSString* filePath = (NSString*)CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle);
+ BOOL shouldEnableFile = [self askFilenameFilter:filePath];
+ [filePath release];
return shouldEnableFile;
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m b/openjdk/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m
index c8044d1..ace6c8e 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -163,8 +163,7 @@ Java_sun_awt_CGraphicsEnvironment_registerDisplayReconfiguration
JNF_COCOA_ENTER(env);
- JNFWeakJObjectWrapper *wrapper = [JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env];
- CFRetain(wrapper); // pin from ObjC-GC
+ JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain];
/* Register the callback */
if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) {
@@ -204,8 +203,7 @@ JNF_COCOA_ENTER(env);
}
[wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear
-
- CFRelease(wrapper);
+ [wrapper release];
JNF_COCOA_EXIT(env);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CImage.m b/openjdk/jdk/src/macosx/native/sun/awt/CImage.m
index ae93d56..eedb31e 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CImage.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CImage.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -115,14 +115,9 @@ JNF_COCOA_ENTER(env);
NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height);
if (imageRep) {
- NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
+ NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] retain];
[nsImage addRepresentation:imageRep];
[imageRep release];
-
- if (nsImage != nil) {
- CFRetain(nsImage); // GC
- }
-
result = ptr_to_jlong(nsImage);
}
@@ -165,13 +160,8 @@ JNF_COCOA_ENTER(env);
(*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT);
}
if ([reps count]) {
- NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)];
+ NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(0, 0)] retain];
[nsImage addRepresentations: reps];
-
- if (nsImage != nil) {
- CFRetain(nsImage); // GC
- }
-
result = ptr_to_jlong(nsImage);
}
@@ -194,8 +184,7 @@ JNF_COCOA_ENTER(env);
IconRef iconRef;
if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) {
- image = [[NSImage alloc] initWithIconRef:iconRef];
- if (image) CFRetain(image); // GC
+ image = [[[NSImage alloc] initWithIconRef:iconRef] retain];
ReleaseIconRef(iconRef);
}
@@ -217,8 +206,7 @@ JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromFile
JNF_COCOA_ENTER(env);
NSString *path = JNFNormalizedNSStringForPath(env, file);
- image = [[NSImage alloc] initByReferencingFile:path];
- if (image) CFRetain(image); // GC
+ image = [[[NSImage alloc] initByReferencingFile:path] retain];
JNF_COCOA_EXIT(env);
@@ -239,9 +227,8 @@ JNF_COCOA_ENTER(env);
NSString *path = JNFNormalizedNSStringForPath(env, file);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- image = [[NSWorkspace sharedWorkspace] iconForFile:path];
+ image = [[[NSWorkspace sharedWorkspace] iconForFile:path] retain];
[image setScalesWhenResized:TRUE];
- if (image) CFRetain(image); // GC
}];
JNF_COCOA_EXIT(env);
@@ -261,8 +248,7 @@ JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromImag
JNF_COCOA_ENTER(env);
- image = [NSImage imageNamed:JNFJavaToNSString(env, name)];
- if (image) CFRetain(image); // GC
+ image = [[NSImage imageNamed:JNFJavaToNSString(env, name)] retain];
JNF_COCOA_EXIT(env);
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CMenu.m b/openjdk/jdk/src/macosx/native/sun/awt/CMenu.m
index e2db11c..fe42ac7 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CMenu.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CMenu.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
- (id)initWithPeer:(jobject)peer {
AWT_ASSERT_APPKIT_THREAD;
// Create the new NSMenu
- self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]];
+ self = [super initWithPeer:peer asSeparator:NO];
if (self) {
fMenu = [NSMenu javaMenuWithTitle:@""];
[fMenu retain];
@@ -52,7 +52,6 @@ AWT_ASSERT_APPKIT_THREAD;
fMenu = nil;
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
- (void)addJavaSubmenu:(CMenu *)submenu {
[ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES];
@@ -134,14 +133,13 @@ AWT_ASSERT_APPKIT_THREAD;
CMenu * createCMenu (jobject cPeerObjGlobal) {
- CMenu *aCMenu = nil;
-
- // We use an array here only to be able to get a return value
- NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
+ __block CMenu *aCMenu = nil;
- [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- aCMenu = (CMenu *)[args objectAtIndex: 0];
+ aCMenu = [[CMenu alloc] initWithPeer:cPeerObjGlobal];
+ // the aCMenu is released in CMenuComponent.dispose()
+ }];
if (aCMenu == nil) {
return 0L;
@@ -169,10 +167,6 @@ JNF_COCOA_ENTER(env);
// Add it to the parent menu
[((CMenu *)jlong_to_ptr(parentMenu)) addJavaSubmenu: aCMenu];
- if (aCMenu) {
- CFRetain(aCMenu); // GC
- [aCMenu release];
- }
JNF_COCOA_EXIT(env);
@@ -209,10 +203,6 @@ JNF_COCOA_ENTER(env);
[parent javaSetHelpMenu: aCMenu];
}
- if (aCMenu) {
- CFRetain(aCMenu); // GC
- [aCMenu release];
- }
JNF_COCOA_EXIT(env);
return ptr_to_jlong(aCMenu);
}
@@ -275,13 +265,9 @@ Java_sun_lwawt_macosx_CMenu_nativeGetNSMenu
NSMenu* nsMenu = NULL;
JNF_COCOA_ENTER(env);
- nsMenu = [((CMenu *)jlong_to_ptr(menuObject)) menu];
-JNF_COCOA_EXIT(env);
-
// Strong retain this menu; it'll get released in Java_apple_laf_ScreenMenu_addMenuListeners
- if (nsMenu) {
- CFRetain(nsMenu); // GC
- }
+ nsMenu = [[((CMenu *)jlong_to_ptr(menuObject)) menu] retain];
+JNF_COCOA_EXIT(env);
return ptr_to_jlong(nsMenu);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CMenuBar.m b/openjdk/jdk/src/macosx/native/sun/awt/CMenuBar.m
index 3bf4f77..2de86be 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CMenuBar.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CMenuBar.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -383,32 +383,21 @@ JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar
(JNIEnv *env, jobject peer)
{
- CMenuBar *aCMenuBar = nil;
+ __block CMenuBar *aCMenuBar = nil;
JNF_COCOA_ENTER(env);
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
- // We use an array here only to be able to get a return value
- NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
-
- [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES];
-
- aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+ aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal];
+ // the aCMenuBar is released in CMenuComponent.dispose()
+ }];
if (aCMenuBar == nil) {
return 0L;
}
- // [args release];
-
- // A strange memory managment after that.
-
-
JNF_COCOA_EXIT(env);
- if (aCMenuBar) {
- CFRetain(aCMenuBar); // GC
- [aCMenuBar release];
- }
return ptr_to_jlong(aCMenuBar);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CMenuComponent.m b/openjdk/jdk/src/macosx/native/sun/awt/CMenuComponent.m
index c8b3766..6847f9b 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CMenuComponent.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CMenuComponent.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,49 +41,11 @@
return self;
}
--(void) cleanup {
- // Used by subclasses
-}
-
--(void) disposer {
+-(void) dealloc {
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
JNFDeleteGlobalRef(env, fPeer);
fPeer = NULL;
- [self cleanup];
-
- CFRelease(self); // GC
+ [super dealloc];
}
-
-// The method is used by all subclasses, since the process of the creation
-// is the same. The only exception is the CMenuItem class.
-- (void) _create_OnAppKitThread: (NSMutableArray *)argValue {
- jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
- CMenuItem *aCMenuItem = [self initWithPeer:cPeerObjGlobal];
- [argValue removeAllObjects];
- [argValue addObject: aCMenuItem];
-}
-
-//-(void) dealloc { [super dealloc]; }
-//- (void)finalize { [super finalize]; }
-
@end
-
-/*
- * Class: sun_lwawt_macosx_CMenuComponent
- * Method: nativeDispose
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_sun_lwawt_macosx_CMenuComponent_nativeDispose
-(JNIEnv *env, jobject peer, jlong menuItemObj)
-{
-JNF_COCOA_ENTER(env);
-
- [ThreadUtilities performOnMainThread:@selector(disposer)
- on:((id)jlong_to_ptr(menuItemObj))
- withObject:nil
- waitUntilDone:NO];
-
-JNF_COCOA_EXIT(env);
-}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.h b/openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.h
index 60a0565..e2c72f2 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.h
+++ openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
}
// Setup
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator;
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator;
- (void) setIsCheckbox;
// Events
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.m b/openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.m
index 219cc5b..12ab99c 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CMenuItem.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,11 +39,11 @@
@implementation CMenuItem
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{
AWT_ASSERT_APPKIT_THREAD;
self = [super initWithPeer:peer];
if (self) {
- if ([asSeparator boolValue]) {
+ if (asSeparator) {
fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem];
[fMenuItem retain];
} else {
@@ -199,12 +199,9 @@ JNF_COCOA_EXIT(env);
}];
}
-- (void)cleanup {
+- (void)dealloc {
[fMenuItem setAction:NULL];
[fMenuItem setTarget:nil];
-}
-
-- (void)dealloc {
[fMenuItem release];
fMenuItem = nil;
@@ -223,14 +220,6 @@ JNF_COCOA_EXIT(env);
fIsCheckbox = YES;
}
-- (void) _createMenuItem_OnAppKitThread: (NSMutableArray *)argValue {
- jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
- NSNumber * asSeparator = (NSNumber *)[argValue objectAtIndex: 1];
- CMenuItem *aCMenuItem = [self initWithPeer: cPeerObjGlobal asSeparator: asSeparator];
- [argValue removeAllObjects];
- [argValue addObject: aCMenuItem];
-}
-
- (NSString *)description {
return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem];
}
@@ -392,24 +381,18 @@ Java_sun_lwawt_macosx_CMenuItem_nativeCreate
(JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
{
- CMenuItem *aCMenuItem = nil;
+ __block CMenuItem *aCMenuItem = nil;
+ BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO;
CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj);
JNF_COCOA_ENTER(env);
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
- NSMutableArray *args = nil;
-
- // Create a new item....
- if (isSeparator == JNI_TRUE) {
- args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES], nil];
- } else {
- args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil];
- }
-
- [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES];
-
- aCMenuItem = (CMenuItem *)[args objectAtIndex: 0];
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+ aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal
+ asSeparator: asSeparator];
+ // the CMenuItem is released in CMenuComponent.dispose()
+ }];
if (aCMenuItem == nil) {
return 0L;
@@ -420,11 +403,6 @@ JNF_COCOA_ENTER(env);
// setLabel will be called after creation completes.
- if (aCMenuItem) {
- CFRetain(aCMenuItem); // GC
- [aCMenuItem release];
- }
-
JNF_COCOA_EXIT(env);
return ptr_to_jlong(aCMenuItem);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CPopupMenu.m b/openjdk/jdk/src/macosx/native/sun/awt/CPopupMenu.m
index 287e97a..cf45651 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CPopupMenu.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CPopupMenu.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,8 +66,6 @@ JNF_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
aCPopupMenu = [[CPopupMenu alloc] initWithPeer:cPeerObjGlobal];
- CFRetain(aCPopupMenu);
- [aCPopupMenu release];
}];
JNF_COCOA_EXIT(env);
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CPrinterJob.m b/openjdk/jdk/src/macosx/native/sun/awt/CPrinterJob.m
index 219f65b..dfcbc1f 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CPrinterJob.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CPrinterJob.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -469,8 +469,6 @@ JNF_COCOA_ENTER(env);
// safety is assured by the java side of this call.
NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
- if (printInfo) CFRetain(printInfo); // GC
- [printInfo release];
result = ptr_to_jlong(printInfo);
@@ -490,7 +488,7 @@ JNF_COCOA_ENTER(env);
if (nsPrintInfo != -1)
{
NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo);
- if (printInfo) CFRelease(printInfo); // GC
+ [printInfo release];
}
JNF_COCOA_EXIT(env);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CSystemColors.m b/openjdk/jdk/src/macosx/native/sun/awt/CSystemColors.m
index 0f3fab5..6c73c82 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CSystemColors.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CSystemColors.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_systemColorsChanged, jc_LWCToolkit, "systemCol
sColors = (NSColor**)malloc(sizeof(NSColor*) * java_awt_SystemColor_NUM_COLORS);
} else {
for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
- if (sColors[i] != NULL) CFRelease(sColors[i]); // GC
+ if (sColors[i] != NULL) [sColors[i] release];
}
}
@@ -108,14 +108,14 @@ static JNF_STATIC_MEMBER_CACHE(jm_systemColorsChanged, jc_LWCToolkit, "systemCol
sColors[java_awt_SystemColor_INFO_TEXT] = [NSColor textColor];
for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
- if (sColors[i] != NULL) CFRetain(sColors[i]); // GC
+ [sColors[i] retain];
}
if (appleColors == nil) {
appleColors = (NSColor**)malloc(sizeof(NSColor*) * sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS);
} else {
for (i = 0; i < sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS; i++) {
- if (appleColors[i] != NULL) CFRelease(appleColors[i]); // GC
+ if (appleColors[i] != NULL) [appleColors[i] release];
}
}
@@ -124,7 +124,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_systemColorsChanged, jc_LWCToolkit, "systemCol
appleColors[sun_lwawt_macosx_LWCToolkit_INACTIVE_SELECTION_FOREGROUND_COLOR] = [NSColor controlDarkShadowColor];
for (i = 0; i < sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS; i++) {
- if (appleColors[i] != NULL) CFRetain(appleColors[i]); // GC
+ [appleColors[i] retain];
}
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/CTrayIcon.m b/openjdk/jdk/src/macosx/native/sun/awt/CTrayIcon.m
index 79ae024..b3967df 100644
--- openjdk/jdk/src/macosx/native/sun/awt/CTrayIcon.m
+++ openjdk/jdk/src/macosx/native/sun/awt/CTrayIcon.m
@@ -136,7 +136,7 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
clickCount = [event clickCount];
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
- static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+ static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
[event type],
[event modifierFlags],
@@ -145,7 +145,8 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) {
(jint)localPoint.x, (jint)localPoint.y,
(jint)absP.x, (jint)absP.y,
[event deltaY],
- [event deltaX]);
+ [event deltaX],
+ [AWTToolkit scrollStateWithEvent: event]);
if (jEvent == nil) {
// Unable to create event by some reason.
return;
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m b/openjdk/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
index df2d98d..4dcbf07 100644
--- openjdk/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
+++ openjdk/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1497,7 +1497,7 @@ PRINT("ImageSD_dispose")
}
if (isdo->nsRef) {
- CFRelease(isdo->nsRef); // GC
+ [isdo->nsRef release];
isdo->nsRef = nil;
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m b/openjdk/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m
index 2078e1d..ffdf8b5 100644
--- openjdk/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m
+++ openjdk/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m
@@ -55,19 +55,6 @@
[super dealloc];
}
-- (void)finalize
-{
- JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
- JNFDeleteWeakGlobalRef(env, fAccessibleAction);
- fAccessibleAction = NULL;
-
- JNFDeleteWeakGlobalRef(env, fComponent);
- fComponent = NULL;
-
- [super finalize];
-}
-
- (NSString *)getDescription
{
@@ -127,19 +114,6 @@
[super dealloc];
}
-- (void)finalize
-{
- JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
- JNFDeleteWeakGlobalRef(env, fTabGroup);
- fTabGroup = NULL;
-
- JNFDeleteWeakGlobalRef(env, fComponent);
- fComponent = NULL;
-
- [super finalize];
-}
-
- (NSString *)getDescription
{
return @"click";
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m b/openjdk/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m
index d37a480..b740d05 100644
--- openjdk/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m
+++ openjdk/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m
@@ -194,20 +194,6 @@ static NSObject *sAttributeNamesLOCK = nil;
[super dealloc];
}
-- (void)finalize
-{
- [self unregisterFromCocoaAXSystem];
-
- JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
- (*env)->DeleteWeakGlobalRef(env, fAccessible);
- fAccessible = NULL;
-
- (*env)->DeleteWeakGlobalRef(env, fComponent);
- fComponent = NULL;
-
- [super finalize];
-}
- (void)postValueChanged
{
@@ -371,8 +357,8 @@ static NSObject *sAttributeNamesLOCK = nil;
// must init freshly -alloc'd object
[newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
- // must hard CFRetain() pointer poked into Java object
- CFRetain(newChild);
+ // must hard retain pointer poked into Java object
+ [newChild retain];
JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
(*env)->DeleteLocalRef(env, jCAX);
@@ -1498,18 +1484,6 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component);
[super dealloc];
}
-- (void)finalize
-{
- JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
- if (fTabGroupAxContext != NULL) {
- JNFDeleteWeakGlobalRef(env, fTabGroupAxContext);
- fTabGroupAxContext = NULL;
- }
-
- [super finalize];
-}
-
- (id)accessibilityValueAttribute
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.h b/openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.h
index c3e1b53..0a57501 100644
--- openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.h
+++ openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.h
@@ -40,6 +40,7 @@ extern jint* gButtonDownMasks;
@interface AWTToolkit : NSObject { }
+ (long) getEventCount;
+ (void) eventCountPlusPlus;
++ (jint) scrollStateWithEvent: (NSEvent*) event;
@end
/*
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.m
index 8b34eba..871f319 100644
--- openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.m
+++ openjdk/jdk/src/macosx/native/sun/awt/LWCToolkit.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,13 @@
#import "sizecalc.h"
+// SCROLL PHASE STATE
+#define SCROLL_PHASE_UNSUPPORTED 1
+#define SCROLL_PHASE_BEGAN 2
+#define SCROLL_PHASE_CONTINUED 3
+#define SCROLL_PHASE_CANCELLED 4
+#define SCROLL_PHASE_ENDED 5
+
int gNumberOfButtons;
jint* gButtonDownMasks;
@@ -54,6 +61,23 @@ static long eventCount;
eventCount++;
}
++ (jint) scrollStateWithEvent: (NSEvent*) event {
+
+ if ([event type] != NSScrollWheel) {
+ return 0;
+ }
+
+ NSEventPhase phase = [event phase];
+ NSEventPhase momentumPhase = [event momentumPhase];
+
+ if (!phase && !momentumPhase) return SCROLL_PHASE_UNSUPPORTED;
+ switch (phase) {
+ case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN;
+ case NSEventPhaseCancelled: return SCROLL_PHASE_CANCELLED;
+ case NSEventPhaseEnded: return SCROLL_PHASE_ENDED;
+ }
+ return SCROLL_PHASE_CONTINUED;
+}
@end
@@ -249,17 +273,15 @@ JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_LWCToolkit_createAWTRunLoopMediato
{
AWT_ASSERT_APPKIT_THREAD;
- AWTRunLoopObject *o = nil;
+ jlong result;
+JNF_COCOA_ENTER(env);
// We double retain because this object is owned by both main thread and "other" thread
// We release in both doAWTRunLoop and stopAWTRunLoop
- o = [[AWTRunLoopObject alloc] init];
- if (o) {
- CFRetain(o); // GC
- CFRetain(o); // GC
- [o release];
- }
- return ptr_to_jlong(o);
+ result = ptr_to_jlong([[[AWTRunLoopObject alloc] init] retain]);
+JNF_COCOA_EXIT(env);
+
+ return result;
}
/*
@@ -296,10 +318,7 @@ JNF_COCOA_ENTER(env);
}
}
-
-
- CFRelease(mediatorObject);
-
+ [mediatorObject release];
JNF_COCOA_EXIT(env);
}
@@ -317,7 +336,7 @@ JNF_COCOA_ENTER(env);
[ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];
- CFRelease(mediatorObject);
+ [mediatorObject release];
JNF_COCOA_EXIT(env);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/awt/PrintModel.m b/openjdk/jdk/src/macosx/native/sun/awt/PrintModel.m
index 8a172d7..bc20285 100644
--- openjdk/jdk/src/macosx/native/sun/awt/PrintModel.m
+++ openjdk/jdk/src/macosx/native/sun/awt/PrintModel.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,6 @@
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
- (BOOL)runPageSetup {
__block BOOL fResult = NO;
@@ -86,8 +85,8 @@ AWT_ASSERT_NOT_APPKIT_THREAD;
fResult = [self safePrintLoop:printerView withEnv:env];
} else {
// Retain these so they don't go away while we're in Java
- CFRetain(self); // GC
- if (printerView) CFRetain(printerView); // GC
+ [self retain];
+ [printerView retain];
static JNF_CLASS_CACHE(jc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob");
static JNF_STATIC_MEMBER_CACHE(jm_detachPrintLoop, jc_CPrinterJob, "detachPrintLoop", "(JJ)V");
@@ -134,8 +133,8 @@ JNF_COCOA_ENTER(env);
[model safePrintLoop:arg withEnv:env];
// These are to match the retains in runPrintLoopWithView:
- if (model) CFRelease(model); // GC
- if (arg) CFRelease(arg); // GC
+ [model release];
+ [arg release];
JNF_COCOA_EXIT(env);
}
diff --git a/openjdk/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m b/openjdk/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
index 5df99a4..39c50af 100644
--- openjdk/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
+++ openjdk/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,6 @@ AWT_ASSERT_APPKIT_THREAD;
[super dealloc];
}
-//- (void)finalize { [super finalize]; }
- (void)finishLaunching
{
diff --git a/openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java b/openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
index 13f2d93..7da36e1 100644
--- openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
+++ openjdk/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
@@ -729,7 +729,11 @@ public class PNGImageReader extends ImageReader {
parse_iCCP_chunk(chunkLength);
break;
case iTXt_TYPE:
- parse_iTXt_chunk(chunkLength);
+ if (ignoreMetadata) {
+ stream.skipBytes(chunkLength);
+ } else {
+ parse_iTXt_chunk(chunkLength);
+ }
break;
case pHYs_TYPE:
parse_pHYs_chunk();
@@ -753,7 +757,11 @@ public class PNGImageReader extends ImageReader {
parse_tRNS_chunk(chunkLength);
break;
case zTXt_TYPE:
- parse_zTXt_chunk(chunkLength);
+ if (ignoreMetadata) {
+ stream.skipBytes(chunkLength);
+ } else {
+ parse_zTXt_chunk(chunkLength);
+ }
break;
default:
// Read an unknown chunk
diff --git a/openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java b/openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java
index ae5c61d..77db225 100644
--- openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java
+++ openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java
@@ -33,6 +33,8 @@ import java.util.Hashtable;
import org.omg.CosNaming.*;
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
/**
* Implements the JNDI NamingEnumeration interface for COS
* Naming. Gets hold of a list of bindings from the COS Naming Server
@@ -212,7 +214,10 @@ final class CNBindingEnumeration
Name cname = CNNameParser.cosNameToName(bndg.binding_name);
try {
+ // Check whether object factory codebase is trusted
+ if (CorbaUtils.isObjectFactoryTrusted(obj)) {
obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
+ }
} catch (NamingException e) {
throw e;
} catch (Exception e) {
diff --git a/openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java b/openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java
index 800c0a5..27dc14e 100644
--- openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java
+++ openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java
@@ -36,6 +36,8 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
@@ -82,6 +84,19 @@ public class CNCtx implements javax.naming.Context {
private static final String FED_PROP = "com.sun.jndi.cosnaming.federation";
boolean federation = false;
+ /**
+ * Determines whether classes may be loaded from an arbitrary URL code base.
+ */
+ public static final boolean trustURLCodebase;
+ static {
+ // System property to control whether classes may be loaded from an
+ // arbitrary URL code base
+ PrivilegedAction<String> act = () -> System.getProperty(
+ "com.sun.jndi.cosnaming.object.trustURLCodebase", "false");
+ String trust = AccessController.doPrivileged(act);
+ trustURLCodebase = "true".equalsIgnoreCase(trust);
+ }
+
// Reference counter for tracking _orb references
OrbReuseTracker orbTracker = null;
int enumCount;
@@ -534,12 +549,16 @@ public class CNCtx implements javax.naming.Context {
if (name.size() == 0 )
return this; // %%% should clone() so that env can be changed
NameComponent[] path = CNNameParser.nameToCosName(name);
+ java.lang.Object answer = null;
try {
- java.lang.Object answer = callResolve(path);
-
+ answer = callResolve(path);
try {
- return NamingManager.getObjectInstance(answer, name, this, _env);
+ // Check whether object factory codebase is trusted
+ if (CorbaUtils.isObjectFactoryTrusted(answer)) {
+ answer = NamingManager.getObjectInstance(
+ answer, name, this, _env);
+ }
} catch (NamingException e) {
throw e;
} catch (Exception e) {
@@ -552,6 +571,7 @@ public class CNCtx implements javax.naming.Context {
javax.naming.Context cctx = getContinuationContext(cpe);
return cctx.lookup(cpe.getRemainingName());
}
+ return answer;
}
/**
diff --git a/openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java b/openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java
index a1e9fd6..f2c91a0 100644
--- openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java
+++ openjdk/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java
@@ -33,6 +33,8 @@ import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
/**
* A convenience class to map the COS Naming exceptions to the JNDI exceptions.
* @author Raj Krishnamurthy
@@ -202,10 +204,13 @@ public final class ExceptionMapper {
// Not a context, use object factory to transform object.
Name cname = CNNameParser.cosNameToName(resolvedName);
- java.lang.Object resolvedObj2;
+ java.lang.Object resolvedObj2 = null;
try {
+ // Check whether object factory codebase is trusted
+ if (CorbaUtils.isObjectFactoryTrusted(resolvedObj)) {
resolvedObj2 = NamingManager.getObjectInstance(resolvedObj,
cname, ctx, ctx._env);
+ }
} catch (NamingException ge) {
throw ge;
} catch (Exception ge) {
diff --git a/openjdk/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/openjdk/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java
index 2990ed8..8b38394 100644
--- openjdk/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java
+++ openjdk/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java
@@ -32,6 +32,8 @@ import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.naming.*;
import javax.naming.spi.NamingManager;
@@ -52,6 +54,18 @@ public class RegistryContext implements Context, Referenceable {
private int port;
private static final NameParser nameParser = new AtomicNameParser();
private static final String SOCKET_FACTORY = "com.sun.jndi.rmi.factory.socket";
+ /**
+ * Determines whether classes may be loaded from an arbitrary URL code base.
+ */
+ static final boolean trustURLCodebase;
+ static {
+ // System property to control whether classes may be loaded from an
+ // arbitrary URL codebase
+ PrivilegedAction<String> act = () -> System.getProperty(
+ "com.sun.jndi.rmi.object.trustURLCodebase", "false");
+ String trust = AccessController.doPrivileged(act);
+ trustURLCodebase = "true".equalsIgnoreCase(trust);
+ }
Reference reference = null; // ref used to create this context, if any
@@ -461,6 +475,27 @@ public class RegistryContext implements Context, Referenceable {
Object obj = (r instanceof RemoteReference)
? ((RemoteReference)r).getReference()
: (Object)r;
+
+ /*
+ * Classes may only be loaded from an arbitrary URL codebase when
+ * the system property com.sun.jndi.rmi.object.trustURLCodebase
+ * has been set to "true".
+ */
+
+ // Use reference if possible
+ Reference ref = null;
+ if (obj instanceof Reference) {
+ ref = (Reference) obj;
+ } else if (obj instanceof Referenceable) {
+ ref = ((Referenceable)(obj)).getReference();
+ }
+
+ if (ref != null && ref.getFactoryClassLocation() != null &&
+ !trustURLCodebase) {
+ throw new ConfigurationException(
+ "The object factory is untrusted. Set the system property" +
+ " 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
+ }
return NamingManager.getObjectInstance(obj, name, this,
environment);
} catch (NamingException e) {
diff --git a/openjdk/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java b/openjdk/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java
index dd32fef..cb92e1b 100644
--- openjdk/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java
+++ openjdk/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java
@@ -36,8 +36,9 @@ import java.util.Enumeration;
import org.omg.CORBA.ORB;
-import javax.naming.Context;
-import javax.naming.ConfigurationException;
+import javax.naming.*;
+
+import com.sun.jndi.cosnaming.CNCtx;
/**
* Contains utilities for performing CORBA-related tasks:
@@ -204,6 +205,32 @@ public class CorbaUtils {
}
/**
+ * Check whether object factory code base is trusted.
+ * Classes may only be loaded from an arbitrary URL code base when
+ * the system property com.sun.jndi.rmi.object.trustURLCodebase
+ * has been set to "true".
+ */
+ public static boolean isObjectFactoryTrusted(Object obj)
+ throws NamingException {
+
+ // Extract Reference, if possible
+ Reference ref = null;
+ if (obj instanceof Reference) {
+ ref = (Reference) obj;
+ } else if (obj instanceof Referenceable) {
+ ref = ((Referenceable)(obj)).getReference();
+ }
+
+ if (ref != null && ref.getFactoryClassLocation() != null &&
+ !CNCtx.trustURLCodebase) {
+ throw new ConfigurationException(
+ "The object factory is untrusted. Set the system property" +
+ " 'com.sun.jndi.cosnaming.object.trustURLCodebase' to 'true'.");
+ }
+ return true;
+ }
+
+ /**
* This method returns a new ORB instance for the given applet
* without creating a static dependency on java.applet.
*/
diff --git a/openjdk/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java b/openjdk/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java
index e161b0e..edcdfa6 100644
--- openjdk/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java
+++ openjdk/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java
@@ -426,7 +426,6 @@ public class LdapLoginModule implements LoginModule {
constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
constraints.setReturningAttributes(new String[0]); //return no attrs
- constraints.setReturningObjFlag(true); // to get the full DN
}
authzIdentity = (String)options.get(AUTHZ_IDENTITY);
@@ -886,11 +885,7 @@ public class LdapLoginModule implements LoginModule {
// (Use the first entry if more than one is returned)
if (results.hasMore()) {
SearchResult entry = results.next();
-
- // %%% - use the SearchResult.getNameInNamespace method
- // available in JDK 1.5 and later.
- // (can remove call to constraints.setReturningObjFlag)
- userDN = ((Context)entry.getObject()).getNameInNamespace();
+ userDN = entry.getNameInNamespace();
if (debug) {
System.out.println("\t\t[LdapLoginModule] found entry: " +
diff --git a/openjdk/jdk/src/share/classes/java/awt/MenuComponent.java b/openjdk/jdk/src/share/classes/java/awt/MenuComponent.java
index b65c843..e1b3a7d 100644
--- openjdk/jdk/src/share/classes/java/awt/MenuComponent.java
+++ openjdk/jdk/src/share/classes/java/awt/MenuComponent.java
@@ -145,6 +145,10 @@ public abstract class MenuComponent implements java.io.Serializable {
public Font getFont_NoClientCode(MenuComponent menuComp) {
return menuComp.getFont_NoClientCode();
}
+ @SuppressWarnings("unchecked")
+ public <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp) {
+ return (T) menuComp.peer;
+ }
});
}
diff --git a/openjdk/jdk/src/share/classes/java/io/ObjectInputStream.java b/openjdk/jdk/src/share/classes/java/io/ObjectInputStream.java
index 9da6182..b5cb828 100644
--- openjdk/jdk/src/share/classes/java/io/ObjectInputStream.java
+++ openjdk/jdk/src/share/classes/java/io/ObjectInputStream.java
@@ -37,13 +37,18 @@ import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+
import static java.io.ObjectStreamClass.processQueue;
+
+import sun.misc.ObjectInputFilter;
import sun.misc.ObjectStreamClassValidator;
import sun.misc.SharedSecrets;
-import sun.misc.Unsafe;
import sun.reflect.misc.ReflectUtil;
+import sun.misc.JavaOISAccess;
+import sun.util.logging.PlatformLogger;
/**
* An ObjectInputStream deserializes primitive data and objects previously
@@ -239,12 +244,48 @@ public class ObjectInputStream
new ReferenceQueue<>();
}
+ static {
+ /* Setup access so sun.misc can invoke package private functions. */
+ sun.misc.SharedSecrets.setJavaOISAccess(new JavaOISAccess() {
+ public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) {
+ stream.setInternalObjectInputFilter(filter);
+ }
+
+ public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {
+ return stream.getInternalObjectInputFilter();
+ }
+ });
+ }
+
+ /*
+ * Separate class to defer initialization of logging until needed.
+ */
+ private static class Logging {
+
+ /*
+ * Logger for ObjectInputFilter results.
+ * Setup the filter logger if it is set to INFO or WARNING.
+ * (Assuming it will not change).
+ */
+ private static final PlatformLogger traceLogger;
+ private static final PlatformLogger infoLogger;
+ static {
+ PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization");
+ infoLogger = (filterLog != null &&
+ filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null;
+ traceLogger = (filterLog != null &&
+ filterLog.isLoggable(PlatformLogger.Level.FINER)) ? filterLog : null;
+ }
+ }
+
/** filter stream for handling block data conversion */
private final BlockDataInputStream bin;
/** validation callback list */
private final ValidationList vlist;
/** recursion depth */
- private int depth;
+ private long depth;
+ /** Total number of references to any type of object, class, enum, proxy, etc. */
+ private long totalObjectRefs;
/** whether stream is closed */
private boolean closed;
@@ -271,6 +312,12 @@ public class ObjectInputStream
private SerialCallbackContext curContext;
/**
+ * Filter of class descriptors and classes read from the stream;
+ * may be null.
+ */
+ private ObjectInputFilter serialFilter;
+
+ /**
* Creates an ObjectInputStream that reads from the specified InputStream.
* A serialization stream header is read from the stream and verified.
* This constructor will block until the corresponding ObjectOutputStream
@@ -297,6 +344,7 @@ public class ObjectInputStream
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
+ serialFilter = ObjectInputFilter.Config.getSerialFilter();
enableOverride = false;
readStreamHeader();
bin.setBlockDataMode(true);
@@ -327,6 +375,7 @@ public class ObjectInputStream
bin = null;
handles = null;
vlist = null;
+ serialFilter = ObjectInputFilter.Config.getSerialFilter();
enableOverride = true;
}
@@ -334,7 +383,7 @@ public class ObjectInputStream
* Read an object from the ObjectInputStream. The class of the object, the
* signature of the class, and the values of the non-transient and
* non-static fields of the class and all of its supertypes are read.
- * Default deserializing for a class can be overriden using the writeObject
+ * Default deserializing for a class can be overridden using the writeObject
* and readObject methods. Objects referenced by this object are read
* transitively so that a complete equivalent graph of objects is
* reconstructed by readObject.
@@ -1076,6 +1125,138 @@ public class ObjectInputStream
}
/**
+ * Returns the serialization filter for this stream.
+ * The serialization filter is the most recent filter set in
+ * {@link #setInternalObjectInputFilter setInternalObjectInputFilter} or
+ * the initial process-wide filter from
+ * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}.
+ *
+ * @return the serialization filter for the stream; may be null
+ */
+ private final ObjectInputFilter getInternalObjectInputFilter() {
+ return serialFilter;
+ }
+
+ /**
+ * Set the serialization filter for the stream.
+ * The filter's {@link ObjectInputFilter#checkInput checkInput} method is called
+ * for each class and reference in the stream.
+ * The filter can check any or all of the class, the array length, the number
+ * of references, the depth of the graph, and the size of the input stream.
+ * <p>
+ * If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED},
+ * {@code null} or throws a {@link RuntimeException},
+ * the active {@code readObject} or {@code readUnshared}
+ * throws {@link InvalidClassException}, otherwise deserialization
+ * continues uninterrupted.
+ * <p>
+ * The serialization filter is initialized to the value of
+ * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}
+ * when the {@code ObjectInputStream} is constructed and can be set
+ * to a custom filter only once.
+ *
+ * @implSpec
+ * The filter, when not {@code null}, is invoked during {@link #readObject readObject}
+ * and {@link #readUnshared readUnshared} for each object
+ * (regular or class) in the stream including the following:
+ * <ul>
+ * <li>each object reference previously deserialized from the stream
+ * (class is {@code null}, arrayLength is -1),
+ * <li>each regular class (class is not {@code null}, arrayLength is -1),
+ * <li>each interface of a dynamic proxy and the dynamic proxy class itself
+ * (class is not {@code null}, arrayLength is -1),
+ * <li>each array is filtered using the array type and length of the array
+ * (class is the array type, arrayLength is the requested length),
+ * <li>each object replaced by its class' {@code readResolve} method
+ * is filtered using the replacement object's class, if not {@code null},
+ * and if it is an array, the arrayLength, otherwise -1,
+ * <li>and each object replaced by {@link #resolveObject resolveObject}
+ * is filtered using the replacement object's class, if not {@code null},
+ * and if it is an array, the arrayLength, otherwise -1.
+ * </ul>
+ *
+ * When the {@link ObjectInputFilter#checkInput checkInput} method is invoked
+ * it is given access to the current class, the array length,
+ * the current number of references already read from the stream,
+ * the depth of nested calls to {@link #readObject readObject} or
+ * {@link #readUnshared readUnshared},
+ * and the implementation dependent number of bytes consumed from the input stream.
+ * <p>
+ * Each call to {@link #readObject readObject} or
+ * {@link #readUnshared readUnshared} increases the depth by 1
+ * before reading an object and decreases by 1 before returning
+ * normally or exceptionally.
+ * The depth starts at {@code 1} and increases for each nested object and
+ * decrements when each nested call returns.
+ * The count of references in the stream starts at {@code 1} and
+ * is increased before reading an object.
+ *
+ * @param filter the filter, may be null
+ * @throws SecurityException if there is security manager and the
+ * {@code SerializablePermission("serialFilter")} is not granted
+ * @throws IllegalStateException if the {@linkplain #getInternalObjectInputFilter() current filter}
+ * is not {@code null} and is not the process-wide filter
+ */
+ private final void setInternalObjectInputFilter(ObjectInputFilter filter) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new SerializablePermission("serialFilter"));
+ }
+ // Allow replacement of the process-wide filter if not already set
+ if (serialFilter != null &&
+ serialFilter != ObjectInputFilter.Config.getSerialFilter()) {
+ throw new IllegalStateException("filter can not be set more than once");
+ }
+ this.serialFilter = filter;
+ }
+
+ /**
+ * Invoke the serialization filter if non-null.
+ * If the filter rejects or an exception is thrown, throws InvalidClassException.
+ *
+ * @param clazz the class; may be null
+ * @param arrayLength the array length requested; use {@code -1} if not creating an array
+ * @throws InvalidClassException if it rejected by the filter or
+ * a {@link RuntimeException} is thrown
+ */
+ private void filterCheck(Class<?> clazz, int arrayLength)
+ throws InvalidClassException {
+ if (serialFilter != null) {
+ RuntimeException ex = null;
+ ObjectInputFilter.Status status;
+ try {
+ status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,
+ totalObjectRefs, depth, bin.getBytesRead()));
+ } catch (RuntimeException e) {
+ // Preventive interception of an exception to log
+ status = ObjectInputFilter.Status.REJECTED;
+ ex = e;
+ }
+ if (status == null ||
+ status == ObjectInputFilter.Status.REJECTED) {
+ // Debug logging of filter checks that fail
+ if (Logging.infoLogger != null) {
+ Logging.infoLogger.info(
+ "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
+ status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
+ Objects.toString(ex, "n/a"));
+ }
+ InvalidClassException ice = new InvalidClassException("filter status: " + status);
+ ice.initCause(ex);
+ throw ice;
+ } else {
+ // Trace logging for those that succeed
+ if (Logging.traceLogger != null) {
+ Logging.traceLogger.finer(
+ "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
+ status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
+ Objects.toString(ex, "n/a"));
+ }
+ }
+ }
+ }
+
+ /**
* Provide access to the persistent fields read from the input stream.
*/
public static abstract class GetField {
@@ -1324,6 +1505,7 @@ public class ObjectInputStream
}
depth++;
+ totalObjectRefs++;
try {
switch (tc) {
case TC_NULL:
@@ -1400,6 +1582,15 @@ public class ObjectInputStream
}
Object rep = resolveObject(obj);
if (rep != obj) {
+ // The type of the original object has been filtered but resolveObject
+ // may have replaced it; filter the replacement's type
+ if (rep != null) {
+ if (rep.getClass().isArray()) {
+ filterCheck(rep.getClass(), Array.getLength(rep));
+ } else {
+ filterCheck(rep.getClass(), -1);
+ }
+ }
handles.setObject(passHandle, rep);
}
return rep;
@@ -1470,6 +1661,7 @@ public class ObjectInputStream
throw new InvalidObjectException(
"cannot read back reference to unshared object");
}
+ filterCheck(null, -1); // just a check for number of references, depth, no class
return obj;
}
@@ -1574,6 +1766,10 @@ public class ObjectInputStream
ReflectUtil.checkProxyPackageAccess(
getClass().getClassLoader(),
cl.getInterfaces());
+ // Filter the interfaces
+ for (Class<?> clazz : cl.getInterfaces()) {
+ filterCheck(clazz, -1);
+ }
}
} catch (ClassNotFoundException ex) {
resolveEx = ex;
@@ -1582,6 +1778,9 @@ public class ObjectInputStream
desc.initProxy(cl, resolveEx, readClassDesc(false));
+ // Call filterCheck on the definition
+ filterCheck(desc.forClass(), -1);
+
handles.finish(descHandle);
passHandle = descHandle;
return desc;
@@ -1629,8 +1828,12 @@ public class ObjectInputStream
desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
+ // Call filterCheck on the definition
+ filterCheck(desc.forClass(), -1);
+
handles.finish(descHandle);
passHandle = descHandle;
+
return desc;
}
@@ -1671,6 +1874,8 @@ public class ObjectInputStream
ObjectStreamClass desc = readClassDesc(false);
int len = bin.readInt();
+ filterCheck(desc.forClass(), len);
+
Object array = null;
Class<?> cl, ccl = null;
if ((cl = desc.forClass()) != null) {
@@ -1819,6 +2024,14 @@ public class ObjectInputStream
rep = cloneArray(rep);
}
if (rep != obj) {
+ // Filter the replacement object
+ if (rep != null) {
+ if (rep.getClass().isArray()) {
+ filterCheck(rep.getClass(), Array.getLength(rep));
+ } else {
+ filterCheck(rep.getClass(), -1);
+ }
+ }
handles.setObject(passHandle, obj = rep);
}
}
@@ -2009,22 +2222,22 @@ public class ObjectInputStream
desc.setPrimFieldValues(obj, primVals);
}
- int objHandle = passHandle;
- ObjectStreamField[] fields = desc.getFields(false);
+ int objHandle = passHandle;
+ ObjectStreamField[] fields = desc.getFields(false);
Object[] objVals = new Object[desc.getNumObjFields()];
- int numPrimFields = fields.length - objVals.length;
- for (int i = 0; i < objVals.length; i++) {
- ObjectStreamField f = fields[numPrimFields + i];
- objVals[i] = readObject0(f.isUnshared());
- if (f.getField() != null) {
- handles.markDependency(objHandle, passHandle);
- }
+ int numPrimFields = fields.length - objVals.length;
+ for (int i = 0; i < objVals.length; i++) {
+ ObjectStreamField f = fields[numPrimFields + i];
+ objVals[i] = readObject0(f.isUnshared());
+ if (f.getField() != null) {
+ handles.markDependency(objHandle, passHandle);
}
+ }
if (obj != null) {
desc.setObjFieldValues(obj, objVals);
}
- passHandle = objHandle;
- }
+ passHandle = objHandle;
+ }
/**
* Reads in and returns IOException that caused serialization to abort.
@@ -2297,6 +2510,51 @@ public class ObjectInputStream
}
/**
+ * Hold a snapshot of values to be passed to an ObjectInputFilter.
+ */
+ static class FilterValues implements ObjectInputFilter.FilterInfo {
+ final Class<?> clazz;
+ final long arrayLength;
+ final long totalObjectRefs;
+ final long depth;
+ final long streamBytes;
+
+ public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs,
+ long depth, long streamBytes) {
+ this.clazz = clazz;
+ this.arrayLength = arrayLength;
+ this.totalObjectRefs = totalObjectRefs;
+ this.depth = depth;
+ this.streamBytes = streamBytes;
+ }
+
+ @Override
+ public Class<?> serialClass() {
+ return clazz;
+ }
+
+ @Override
+ public long arrayLength() {
+ return arrayLength;
+ }
+
+ @Override
+ public long references() {
+ return totalObjectRefs;
+ }
+
+ @Override
+ public long depth() {
+ return depth;
+ }
+
+ @Override
+ public long streamBytes() {
+ return streamBytes;
+ }
+ }
+
+ /**
* Input stream supporting single-byte peek operations.
*/
private static class PeekInputStream extends InputStream {
@@ -2305,6 +2563,8 @@ public class ObjectInputStream
private final InputStream in;
/** peeked byte */
private int peekb = -1;
+ /** total bytes read from the stream */
+ private long totalBytesRead = 0;
/**
* Creates new PeekInputStream on top of given underlying stream.
@@ -2318,7 +2578,12 @@ public class ObjectInputStream
* that it does not consume the read value.
*/
int peek() throws IOException {
- return (peekb >= 0) ? peekb : (peekb = in.read());
+ if (peekb >= 0) {
+ return peekb;
+ }
+ peekb = in.read();
+ totalBytesRead += peekb >= 0 ? 1 : 0;
+ return peekb;
}
public int read() throws IOException {
@@ -2327,21 +2592,27 @@ public class ObjectInputStream
peekb = -1;
return v;
} else {
- return in.read();
+ int nbytes = in.read();
+ totalBytesRead += nbytes >= 0 ? 1 : 0;
+ return nbytes;
}
}
public int read(byte[] b, int off, int len) throws IOException {
+ int nbytes;
if (len == 0) {
return 0;
} else if (peekb < 0) {
- return in.read(b, off, len);
+ nbytes = in.read(b, off, len);
+ totalBytesRead += nbytes >= 0 ? nbytes : 0;
+ return nbytes;
} else {
b[off++] = (byte) peekb;
len--;
peekb = -1;
- int n = in.read(b, off, len);
- return (n >= 0) ? (n + 1) : 1;
+ nbytes = in.read(b, off, len);
+ totalBytesRead += nbytes >= 0 ? nbytes : 0;
+ return (nbytes >= 0) ? (nbytes + 1) : 1;
}
}
@@ -2366,7 +2637,9 @@ public class ObjectInputStream
skipped++;
n--;
}
- return skipped + skip(n);
+ n = skipped + in.skip(n);
+ totalBytesRead += n;
+ return n;
}
public int available() throws IOException {
@@ -2376,6 +2649,10 @@ public class ObjectInputStream
public void close() throws IOException {
in.close();
}
+
+ public long getBytesRead() {
+ return totalBytesRead;
+ }
}
/**
@@ -3231,6 +3508,14 @@ public class ObjectInputStream
throw new UTFDataFormatException();
}
}
+
+ /**
+ * Returns the number of bytes read from the input stream.
+ * @return the number of bytes read from the input stream
+ */
+ long getBytesRead() {
+ return in.getBytesRead();
+ }
}
/**
diff --git a/openjdk/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/openjdk/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
index acac29b..7b9353a 100644
--- openjdk/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
+++ openjdk/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
@@ -680,7 +680,9 @@ public class MethodHandles {
// disallow lookup more restricted packages
if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
if (name.startsWith("java.") ||
- (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
+ (name.startsWith("sun.")
+ && !name.startsWith("sun.invoke.")
+ && !name.equals("sun.reflect.ReflectionFactory"))) {
throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
}
}
diff --git a/openjdk/jdk/src/share/classes/java/net/SocketInputStream.java b/openjdk/jdk/src/share/classes/java/net/SocketInputStream.java
index 41b18bd..f9a50a0 100644
--- openjdk/jdk/src/share/classes/java/net/SocketInputStream.java
+++ openjdk/jdk/src/share/classes/java/net/SocketInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -155,11 +155,12 @@ class SocketInputStream extends FileInputStream
}
// bounds check
- if (length <= 0 || off < 0 || off + length > b.length) {
+ if (length <= 0 || off < 0 || length > b.length - off) {
if (length == 0) {
return 0;
}
- throw new ArrayIndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException("length == " + length
+ + " off == " + off + " buffer length == " + b.length);
}
boolean gotReset = false;
diff --git a/openjdk/jdk/src/share/classes/java/net/SocketOutputStream.java b/openjdk/jdk/src/share/classes/java/net/SocketOutputStream.java
index 2404e95..20a63e6 100644
--- openjdk/jdk/src/share/classes/java/net/SocketOutputStream.java
+++ openjdk/jdk/src/share/classes/java/net/SocketOutputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -97,11 +97,13 @@ class SocketOutputStream extends FileOutputStream
*/
private void socketWrite(byte b[], int off, int len) throws IOException {
- if (len <= 0 || off < 0 || off + len > b.length) {
+
+ if (len <= 0 || off < 0 || len > b.length - off) {
if (len == 0) {
return;
}
- throw new ArrayIndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException("len == " + len
+ + " off == " + off + " buffer length == " + b.length);
}
FileDescriptor fd = impl.acquireFD();
diff --git a/openjdk/jdk/src/share/classes/java/net/URL.java b/openjdk/jdk/src/share/classes/java/net/URL.java
index a6cbcbc..919825a 100644
--- openjdk/jdk/src/share/classes/java/net/URL.java
+++ openjdk/jdk/src/share/classes/java/net/URL.java
@@ -1364,9 +1364,6 @@ public final class URL implements java.io.Serializable {
path = file;
}
- if (port == -1) {
- port = 0;
- }
// Set the object fields.
this.protocol = protocol;
this.host = host;
diff --git a/openjdk/jdk/src/share/classes/java/net/URLClassLoader.java b/openjdk/jdk/src/share/classes/java/net/URLClassLoader.java
index a3038e2..c2394c7 100644
--- openjdk/jdk/src/share/classes/java/net/URLClassLoader.java
+++ openjdk/jdk/src/share/classes/java/net/URLClassLoader.java
@@ -103,8 +103,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ ucp = new URLClassPath(urls, acc);
}
URLClassLoader(URL[] urls, ClassLoader parent,
@@ -115,8 +115,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- ucp = new URLClassPath(urls);
this.acc = acc;
+ ucp = new URLClassPath(urls, acc);
}
/**
@@ -147,8 +147,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ ucp = new URLClassPath(urls, acc);
}
URLClassLoader(URL[] urls, AccessControlContext acc) {
@@ -158,8 +158,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- ucp = new URLClassPath(urls);
this.acc = acc;
+ ucp = new URLClassPath(urls, acc);
}
/**
@@ -191,8 +191,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- ucp = new URLClassPath(urls, factory);
acc = AccessController.getContext();
+ ucp = new URLClassPath(urls, factory, acc);
}
/* A map (used as a set) to keep track of closeable local resources
diff --git a/openjdk/jdk/src/share/classes/java/net/URLStreamHandler.java b/openjdk/jdk/src/share/classes/java/net/URLStreamHandler.java
index a77c5ed..5130559 100644
--- openjdk/jdk/src/share/classes/java/net/URLStreamHandler.java
+++ openjdk/jdk/src/share/classes/java/net/URLStreamHandler.java
@@ -161,9 +161,9 @@ public abstract class URLStreamHandler {
(spec.charAt(start + 1) == '/')) {
start += 2;
i = spec.indexOf('/', start);
- if (i < 0) {
+ if (i < 0 || i > limit) {
i = spec.indexOf('?', start);
- if (i < 0)
+ if (i < 0 || i > limit)
i = limit;
}
@@ -171,8 +171,14 @@ public abstract class URLStreamHandler {
int ind = authority.indexOf('@');
if (ind != -1) {
- userInfo = authority.substring(0, ind);
- host = authority.substring(ind+1);
+ if (ind != authority.lastIndexOf('@')) {
+ // more than one '@' in authority. This is not server based
+ userInfo = null;
+ host = null;
+ } else {
+ userInfo = authority.substring(0, ind);
+ host = authority.substring(ind+1);
+ }
} else {
userInfo = null;
}
diff --git a/openjdk/jdk/src/share/classes/java/rmi/MarshalledObject.java b/openjdk/jdk/src/share/classes/java/rmi/MarshalledObject.java
index b5f8b73..18f4aba 100644
--- openjdk/jdk/src/share/classes/java/rmi/MarshalledObject.java
+++ openjdk/jdk/src/share/classes/java/rmi/MarshalledObject.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,14 @@ import java.io.ObjectOutputStream;
import java.io.ObjectStreamConstants;
import java.io.OutputStream;
import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import sun.rmi.server.MarshalInputStream;
import sun.rmi.server.MarshalOutputStream;
+import sun.misc.ObjectInputFilter;
+
/**
* A <code>MarshalledObject</code> contains a byte stream with the serialized
* representation of an object given to its constructor. The <code>get</code>
@@ -90,6 +95,9 @@ public final class MarshalledObject<T> implements Serializable {
*/
private int hash;
+ /** Filter used when creating the instance from a stream; may be null. */
+ private transient ObjectInputFilter objectInputFilter = null;
+
/** Indicate compatibility with 1.2 version of class. */
private static final long serialVersionUID = 8988374069173025854L;
@@ -133,6 +141,20 @@ public final class MarshalledObject<T> implements Serializable {
}
/**
+ * Reads in the state of the object and saves the stream's
+ * serialization filter to be used when the object is deserialized.
+ *
+ * @param stream the stream
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a class cannot be found
+ */
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject(); // read in all fields
+ objectInputFilter = ObjectInputFilter.Config.getObjectInputFilter(stream);
+ }
+
+ /**
* Returns a new copy of the contained marshalledobject. The internal
* representation is deserialized with the semantics used for
* unmarshaling parameters for RMI calls.
@@ -155,7 +177,7 @@ public final class MarshalledObject<T> implements Serializable {
ByteArrayInputStream lin =
(locBytes == null ? null : new ByteArrayInputStream(locBytes));
MarshalledObjectInputStream in =
- new MarshalledObjectInputStream(bin, lin);
+ new MarshalledObjectInputStream(bin, lin, objectInputFilter);
@SuppressWarnings("unchecked")
T obj = (T) in.readObject();
in.close();
@@ -295,11 +317,24 @@ public final class MarshalledObject<T> implements Serializable {
* <code>null</code>, then all annotations will be
* <code>null</code>.
*/
- MarshalledObjectInputStream(InputStream objIn, InputStream locIn)
+ MarshalledObjectInputStream(InputStream objIn, InputStream locIn,
+ ObjectInputFilter filter)
throws IOException
{
super(objIn);
this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));
+ if (filter != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this, filter);
+ if (MarshalledObjectInputStream.this.locIn != null) {
+ ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this.locIn, filter);
+ }
+ return null;
+ }
+ });
+ }
}
/**
diff --git a/openjdk/jdk/src/share/classes/java/time/format/ZoneName.java b/openjdk/jdk/src/share/classes/java/time/format/ZoneName.java
index f1f6170..6452413 100644
--- openjdk/jdk/src/share/classes/java/time/format/ZoneName.java
+++ openjdk/jdk/src/share/classes/java/time/format/ZoneName.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,8 @@
package java.time.format;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
/**
* A helper class to map a zone name to metazone and back to the
@@ -335,6 +332,7 @@ class ZoneName {
"America/Eirunepe", "Amazon", "America/Manaus",
"Africa/Nairobi", "Africa_Eastern", "Africa/Nairobi",
"Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk",
+ "Asia/Yangon", "Myanmar", "Asia/Rangoon",
"America/Goose_Bay", "Atlantic", "America/Halifax",
"Africa/Maseru", "Africa_Southern", "Africa/Johannesburg",
"America/Swift_Current", "America_Central", "America/Chicago",
@@ -770,6 +768,7 @@ class ZoneName {
"America/Indianapolis", "America/Indiana/Indianapolis",
"Europe/Belfast", "Europe/London",
"America/Kralendijk", "America/Curacao",
+ "Asia/Rangoon", "Asia/Yangon",
};
private static final Map<String, String> zidToMzone = new HashMap<>();
diff --git a/openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index c10abcc..990f3e8 100644
--- openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -40,6 +40,7 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import sun.reflect.CallerSensitive;
@@ -410,7 +411,17 @@ public abstract class AtomicIntegerFieldUpdater<T> {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -432,6 +443,21 @@ public abstract class AtomicIntegerFieldUpdater<T> {
}
/**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(getPackageName(class1), getPackageName(class2));
+ }
+
+ private static String getPackageName(Class<?> cls) {
+ String cn = cls.getName();
+ int dot = cn.lastIndexOf('.');
+ return (dot != -1) ? cn.substring(0, dot) : "";
+ }
+
+ /**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
diff --git a/openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index e701c67..b1d14c5 100644
--- openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -40,6 +40,7 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import sun.reflect.CallerSensitive;
@@ -408,7 +409,17 @@ public abstract class AtomicLongFieldUpdater<T> {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -539,7 +550,17 @@ public abstract class AtomicLongFieldUpdater<T> {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -620,4 +641,19 @@ public abstract class AtomicLongFieldUpdater<T> {
} while (acl != null);
return false;
}
+
+ /**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(getPackageName(class1), getPackageName(class2));
+}
+
+ private static String getPackageName(Class<?> cls) {
+ String cn = cls.getName();
+ int dot = cn.lastIndexOf('.');
+ return (dot != -1) ? cn.substring(0, dot) : "";
+ }
}
diff --git a/openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 76fa0a7..cd18e48 100644
--- openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -40,6 +40,7 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import sun.reflect.CallerSensitive;
@@ -346,7 +347,17 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.vclass = vclass;
this.offset = U.objectFieldOffset(field);
@@ -369,6 +380,21 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
}
/**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(getPackageName(class1), getPackageName(class2));
+ }
+
+ private static String getPackageName(Class<?> cls) {
+ String cn = cls.getName();
+ int dot = cn.lastIndexOf('.');
+ return (dot != -1) ? cn.substring(0, dot) : "";
+ }
+
+ /**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
diff --git a/openjdk/jdk/src/share/classes/java/util/logging/Level.java b/openjdk/jdk/src/share/classes/java/util/logging/Level.java
index f4e66ef..e42336d 100644
--- openjdk/jdk/src/share/classes/java/util/logging/Level.java
+++ openjdk/jdk/src/share/classes/java/util/logging/Level.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -599,11 +599,14 @@ public class Level implements java.io.Serializable {
if (list != null) {
for (KnownLevel level : list) {
Level other = level.mirroredLevel;
+ Class<? extends Level> type = level.levelObject.getClass();
if (l.value == other.value &&
(l.resourceBundleName == other.resourceBundleName ||
(l.resourceBundleName != null &&
l.resourceBundleName.equals(other.resourceBundleName)))) {
- return level;
+ if (type == l.getClass()) {
+ return level;
+ }
}
}
}
diff --git a/openjdk/jdk/src/share/classes/java/util/logging/LogRecord.java b/openjdk/jdk/src/share/classes/java/util/logging/LogRecord.java
index d9255f4..9080bbc 100644
--- openjdk/jdk/src/share/classes/java/util/logging/LogRecord.java
+++ openjdk/jdk/src/share/classes/java/util/logging/LogRecord.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -502,13 +502,21 @@ public class LogRecord implements java.io.Serializable {
throw new IOException("LogRecord: bad version: " + major + "." + minor);
}
int len = in.readInt();
- if (len == -1) {
+ if (len < -1) {
+ throw new NegativeArraySizeException();
+ } else if (len == -1) {
parameters = null;
- } else {
+ } else if (len < 255) {
parameters = new Object[len];
for (int i = 0; i < parameters.length; i++) {
parameters[i] = in.readObject();
}
+ } else {
+ List<Object> params = new ArrayList<>(Math.min(len, 1024));
+ for (int i = 0; i < len; i++) {
+ params.add(in.readObject());
+ }
+ parameters = params.toArray(new Object[params.size()]);
}
// If necessary, try to regenerate the resource bundle.
if (resourceBundleName != null) {
diff --git a/openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
index d886cb6..b1f3815 100644
--- openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+++ openjdk/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -349,7 +349,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+", unwrapping parameters using classLoaderWithRepository.");
values =
- nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class));
+ nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
try {
final Object params2[] =
@@ -413,7 +413,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
values = nullIsEmpty(unwrap(params,
getClassLoader(loaderName),
defaultClassLoader,
- Object[].class));
+ Object[].class,delegationSubject));
try {
final Object params2[] =
@@ -524,7 +524,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
"connectionId=" + connectionId
+" unwrapping query with defaultClassLoader.");
- queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+ queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
try {
final Object params[] = new Object[] { name, queryValue };
@@ -559,7 +559,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
"connectionId=" + connectionId
+" unwrapping query with defaultClassLoader.");
- queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+ queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
try {
final Object params[] = new Object[] { name, queryValue };
@@ -709,7 +709,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
attr = unwrap(attribute,
getClassLoaderFor(name),
defaultClassLoader,
- Attribute.class);
+ Attribute.class, delegationSubject);
try {
final Object params[] = new Object[] { name, attr };
@@ -760,7 +760,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
unwrap(attributes,
getClassLoaderFor(name),
defaultClassLoader,
- AttributeList.class);
+ AttributeList.class, delegationSubject);
try {
final Object params[] = new Object[] { name, attrlist };
@@ -812,7 +812,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
values = nullIsEmpty(unwrap(params,
getClassLoaderFor(name),
defaultClassLoader,
- Object[].class));
+ Object[].class, delegationSubject));
try {
final Object params2[] =
@@ -992,7 +992,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
filterValues[i] =
unwrap(filters[i], targetCl, defaultClassLoader,
- NotificationFilter.class);
+ NotificationFilter.class, sbjs[i]);
if (debug) logger.debug("addNotificationListener"+
"(ObjectName,NotificationFilter)",
@@ -1060,7 +1060,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+" unwrapping filter with target extended ClassLoader.");
filterValue =
- unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
+ unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
if (debug) logger.debug("addNotificationListener"+
"(ObjectName,ObjectName,NotificationFilter,Object)",
@@ -1068,7 +1068,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+" unwrapping handback with target extended ClassLoader.");
handbackValue =
- unwrap(handback, targetCl, defaultClassLoader, Object.class);
+ unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
try {
final Object params[] =
@@ -1199,7 +1199,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+" unwrapping filter with target extended ClassLoader.");
filterValue =
- unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
+ unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
if (debug) logger.debug("removeNotificationListener"+
"(ObjectName,ObjectName,NotificationFilter,Object)",
@@ -1207,7 +1207,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+" unwrapping handback with target extended ClassLoader.");
handbackValue =
- unwrap(handback, targetCl, defaultClassLoader, Object.class);
+ unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
try {
final Object params[] =
@@ -1551,20 +1551,38 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
}
}
- private static <T> T unwrap(final MarshalledObject<?> mo,
+ private <T> T unwrap(final MarshalledObject<?> mo,
final ClassLoader cl,
- final Class<T> wrappedClass)
+ final Class<T> wrappedClass,
+ Subject delegationSubject)
throws IOException {
if (mo == null) {
return null;
}
try {
final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
- try {
- return wrappedClass.cast(mo.get());
- } catch (ClassNotFoundException cnfe) {
- throw new UnmarshalException(cnfe.toString(), cnfe);
- } finally {
+ try{
+ final AccessControlContext reqACC;
+ if (delegationSubject == null)
+ reqACC = acc;
+ else {
+ if (subject == null) {
+ final String msg =
+ "Subject delegation cannot be enabled unless " +
+ "an authenticated subject is put in place";
+ throw new SecurityException(msg);
+ }
+ reqACC = subjectDelegator.delegatedContext(
+ acc, delegationSubject, removeCallerContext);
+ }
+ if(reqACC != null){
+ return AccessController.doPrivileged(
+ (PrivilegedExceptionAction<T>) () ->
+ wrappedClass.cast(mo.get()), reqACC);
+ }else{
+ return wrappedClass.cast(mo.get());
+ }
+ }finally{
AccessController.doPrivileged(new SetCcl(old));
}
} catch (PrivilegedActionException pe) {
@@ -1577,14 +1595,19 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
}
logger.warning("unwrap", "Failed to unmarshall object: " + e);
logger.debug("unwrap", e);
+ }catch (ClassNotFoundException ex) {
+ logger.warning("unwrap", "Failed to unmarshall object: " + ex);
+ logger.debug("unwrap", ex);
+ throw new UnmarshalException(ex.toString(), ex);
}
return null;
}
- private static <T> T unwrap(final MarshalledObject<?> mo,
+ private <T> T unwrap(final MarshalledObject<?> mo,
final ClassLoader cl1,
final ClassLoader cl2,
- final Class<T> wrappedClass)
+ final Class<T> wrappedClass,
+ Subject delegationSubject)
throws IOException {
if (mo == null) {
return null;
@@ -1598,7 +1621,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
}
}
);
- return unwrap(mo, orderCL, wrappedClass);
+ return unwrap(mo, orderCL, wrappedClass,delegationSubject);
} catch (PrivilegedActionException pe) {
Exception e = extractException(pe);
if (e instanceof IOException) {
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java
index f5cdec5..b7de1ff 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $
@@ -38,7 +38,6 @@ import org.w3c.dom.Node;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
import com.sun.org.apache.xml.internal.security.transforms.Transform;
-import com.sun.org.apache.xml.internal.security.transforms.Transforms;
import javax.xml.crypto.*;
import javax.xml.crypto.dom.DOMCryptoContext;
@@ -150,7 +149,7 @@ public abstract class ApacheTransform extends TransformService {
if (Utils.secureValidation(xc)) {
String algorithm = getAlgorithm();
- if (Transforms.TRANSFORM_XSLT.equals(algorithm)) {
+ if (Policy.restrictAlg(algorithm)) {
throw new TransformException(
"Transform " + algorithm + " is forbidden when secure validation is enabled"
);
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java
index bbc483b..d8fc21c 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -113,9 +113,10 @@ public final class DOMManifest extends DOMStructure implements Manifest {
localName + ", expected Reference");
}
refs.add(new DOMReference(refElem, context, provider));
- if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) {
- String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " "
- + "references per Manifest are allowed with secure validation";
+ if (secVal && Policy.restrictNumReferences(refs.size())) {
+ String error = "A maximum of " + Policy.maxReferences()
+ + " references per Manifest are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
refElem = DOMUtils.getNextSiblingElement(refElem);
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java
index 5896183..dbb9be5 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* ===========================================================================
@@ -51,7 +51,6 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.jcp.xml.dsig.internal.DigesterOutputStream;
-import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
import com.sun.org.apache.xml.internal.security.utils.Base64;
@@ -67,11 +66,6 @@ public final class DOMReference extends DOMStructure
implements Reference, DOMURIReference {
/**
- * The maximum number of transforms per reference, if secure validation is enabled.
- */
- public static final int MAXIMUM_TRANSFORM_COUNT = 5;
-
- /**
* Look up useC14N11 system property. If true, an explicit C14N11 transform
* will be added if necessary when generating the signature. See section
* 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info.
@@ -217,9 +211,10 @@ public final class DOMReference extends DOMStructure
}
transforms.add
(new DOMTransform(transformElem, context, provider));
- if (secVal && (transforms.size() > MAXIMUM_TRANSFORM_COUNT)) {
- String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " "
- + "transforms per Reference are allowed with secure validation";
+ if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+ String error = "A maximum of " + Policy.maxTransforms()
+ + " transforms per Reference are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -236,10 +231,10 @@ public final class DOMReference extends DOMStructure
Element dmElem = nextSibling;
this.digestMethod = DOMDigestMethod.unmarshal(dmElem);
String digestMethodAlgorithm = this.digestMethod.getAlgorithm();
- if (secVal
- && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) {
+ if (secVal && Policy.restrictAlg(digestMethodAlgorithm)) {
throw new MarshalException(
- "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled"
+ "It is forbidden to use algorithm " + digestMethodAlgorithm +
+ " when secure validation is enabled"
);
}
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
index 2e8ccbe..73d8019 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* ===========================================================================
@@ -154,9 +154,10 @@ public final class DOMRetrievalMethod extends DOMStructure
}
transforms.add
(new DOMTransform(transformElem, context, provider));
- if (secVal && (transforms.size() > DOMReference.MAXIMUM_TRANSFORM_COUNT)) {
- String error = "A maxiumum of " + DOMReference.MAXIMUM_TRANSFORM_COUNT + " "
- + "transforms per Reference are allowed with secure validation";
+ if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+ String error = "A maximum of " + Policy.maxTransforms()
+ + " transforms per Reference are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -243,7 +244,8 @@ public final class DOMRetrievalMethod extends DOMStructure
}
// guard against RetrievalMethod loops
- if ((data instanceof NodeSetData) && Utils.secureValidation(context)) {
+ if ((data instanceof NodeSetData) && Utils.secureValidation(context)
+ && Policy.restrictRetrievalMethodLoops()) {
NodeSetData nsd = (NodeSetData)data;
Iterator i = nsd.iterator();
if (i.hasNext()) {
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
index bb615d2..bc90eab 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMSignatureMethod.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -41,6 +41,7 @@ import org.w3c.dom.Element;
import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA;
import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
import org.jcp.xml.dsig.internal.SignerOutputStream;
+import sun.security.util.KeyUtil;
/**
* DOM-based abstract implementation of SignatureMethod.
@@ -162,6 +163,7 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
if (!(key instanceof PublicKey)) {
throw new InvalidKeyException("key must be PublicKey");
}
+ checkKeySize(context, key);
if (signature == null) {
try {
Provider p = (Provider)context.getProperty
@@ -197,6 +199,37 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
}
}
+ /**
+ * If secure validation mode is enabled, checks that the key size is
+ * restricted.
+ *
+ * @param context the context
+ * @param key the key to check
+ * @throws XMLSignatureException if the key size is restricted
+ */
+ private static void checkKeySize(XMLCryptoContext context, Key key)
+ throws XMLSignatureException {
+ if (Utils.secureValidation(context)) {
+ int size = KeyUtil.getKeySize(key);
+ if (size == -1) {
+ // key size cannot be determined, so we cannot check against
+ // restrictions. Note that a DSA key w/o params will be
+ // rejected later if the certificate chain is validated.
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Size for " +
+ key.getAlgorithm() + " key cannot be determined");
+ }
+ return;
+ }
+ if (Policy.restrictKey(key.getAlgorithm(), size)) {
+ throw new XMLSignatureException(key.getAlgorithm() +
+ " keys less than " +
+ Policy.minKeySize(key.getAlgorithm()) + " bits are" +
+ " forbidden when secure validation is enabled");
+ }
+ }
+ }
+
byte[] sign(Key key, SignedInfo si, XMLSignContext context)
throws InvalidKeyException, XMLSignatureException
{
@@ -207,6 +240,7 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
if (!(key instanceof PrivateKey)) {
throw new InvalidKeyException("key must be PrivateKey");
}
+ checkKeySize(context, key);
if (signature == null) {
try {
Provider p = (Provider)context.getProperty
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
index d86dd1b..3e2f799 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
@@ -21,7 +21,7 @@
* under the License.
*/
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -45,7 +45,6 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.sun.org.apache.xml.internal.security.utils.Base64;
-import com.sun.org.apache.xml.internal.security.utils.Constants;
import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
/**
@@ -55,22 +54,9 @@ import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream
*/
public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
- /**
- * The maximum number of references per Manifest, if secure validation is enabled.
- */
- public static final int MAXIMUM_REFERENCE_COUNT = 30;
-
private static java.util.logging.Logger log =
java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
- /** Signature - NOT Recommended RSAwithMD5 */
- private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
- Constants.MoreAlgorithmsSpecNS + "rsa-md5";
-
- /** HMAC - NOT Recommended HMAC-MD5 */
- private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
- Constants.MoreAlgorithmsSpecNS + "hmac-md5";
-
private List<Reference> references;
private CanonicalizationMethod canonicalizationMethod;
private SignatureMethod signatureMethod;
@@ -163,10 +149,10 @@ public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
boolean secVal = Utils.secureValidation(context);
String signatureMethodAlgorithm = signatureMethod.getAlgorithm();
- if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm)
- || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) {
+ if (secVal && Policy.restrictAlg(signatureMethodAlgorithm)) {
throw new MarshalException(
- "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled"
+ "It is forbidden to use algorithm " + signatureMethodAlgorithm +
+ " when secure validation is enabled"
);
}
@@ -184,9 +170,10 @@ public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
}
refList.add(new DOMReference(refElem, context, provider));
- if (secVal && (refList.size() > MAXIMUM_REFERENCE_COUNT)) {
- String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " "
- + "references per Manifest are allowed with secure validation";
+ if (secVal && Policy.restrictNumReferences(refList.size())) {
+ String error = "A maximum of " + Policy.maxReferences()
+ + " references per Manifest are allowed when"
+ + " secure validation is enabled";
throw new MarshalException(error);
}
refElem = DOMUtils.getNextSiblingElement(refElem);
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
index 209de66..72791df 100644
--- openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
@@ -73,6 +73,11 @@ public class DOMURIDereferencer implements URIDereferencer {
boolean secVal = Utils.secureValidation(context);
+ if (secVal && Policy.restrictReferenceUriScheme(uri)) {
+ throw new URIReferenceException(
+ "Uri " + uri + " is forbidden when secure validation is enabled");
+ }
+
// Check if same-document URI and already registered on the context
if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') {
String id = uri.substring(1);
@@ -83,12 +88,19 @@ public class DOMURIDereferencer implements URIDereferencer {
id = id.substring(i1+1, i2);
}
- Node referencedElem = dcc.getElementById(id);
+ // check if element is registered by Id
+ Node referencedElem = uriAttr.getOwnerDocument().getElementById(id);
+ if (referencedElem == null) {
+ // see if element is registered in DOMCryptoContext
+ referencedElem = dcc.getElementById(id);
+ }
if (referencedElem != null) {
- if (secVal) {
+ if (secVal && Policy.restrictDuplicateIds()) {
Element start = referencedElem.getOwnerDocument().getDocumentElement();
if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) {
- String error = "Multiple Elements with the same ID " + id + " were detected";
+ String error = "Multiple Elements with the same ID "
+ + id + " detected when secure validation"
+ + " is enabled";
throw new URIReferenceException(error);
}
}
@@ -110,9 +122,9 @@ public class DOMURIDereferencer implements URIDereferencer {
try {
ResourceResolver apacheResolver =
- ResourceResolver.getInstance(uriAttr, baseURI, secVal);
+ ResourceResolver.getInstance(uriAttr, baseURI, false);
XMLSignatureInput in = apacheResolver.resolve(uriAttr,
- baseURI, secVal);
+ baseURI, false);
if (in.isOctetStream()) {
return new ApacheOctetStreamData(in);
} else {
diff --git a/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java b/openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java
new file mode 100644
index 0000000..1608ad8
--- /dev/null
+++ openjdk/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jcp.xml.dsig.internal.dom;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The secure validation policy as specified by the
+ * jdk.xml.dsig.secureValidationPolicy security property.
+ */
+public final class Policy {
+
+ // all restrictions are initialized to be unconstrained
+ private static Set<URI> disallowedAlgs = new HashSet<>();
+ private static int maxTrans = Integer.MAX_VALUE;
+ private static int maxRefs = Integer.MAX_VALUE;
+ private static Set<String> disallowedRefUriSchemes = new HashSet<>();
+ private static Map<String, Integer> minKeyMap = new HashMap<>();
+ private static boolean noDuplicateIds = false;
+ private static boolean noRMLoops = false;
+
+ static {
+ try {
+ initialize();
+ } catch (Exception e) {
+ throw new SecurityException(
+ "Cannot initialize the secure validation policy", e);
+ }
+ }
+
+ private Policy() {}
+
+ private static void initialize() {
+ String prop =
+ AccessController.doPrivileged((PrivilegedAction<String>) () ->
+ Security.getProperty("jdk.xml.dsig.secureValidationPolicy"));
+ if (prop == null || prop.isEmpty()) {
+ // no policy specified, so don't enforce any restrictions
+ return;
+ }
+ String[] entries = prop.split(",");
+ for (String entry : entries) {
+ String[] tokens = entry.split("\\s");
+ String type = tokens[0];
+ switch(type) {
+ case "disallowAlg":
+ if (tokens.length != 2) {
+ error(entry);
+ }
+ disallowedAlgs.add(URI.create(tokens[1]));
+ break;
+ case "maxTransforms":
+ if (tokens.length != 2) {
+ error(entry);
+ }
+ maxTrans = Integer.parseUnsignedInt(tokens[1]);
+ break;
+ case "maxReferences":
+ if (tokens.length != 2) {
+ error(entry);
+ }
+ maxRefs = Integer.parseUnsignedInt(tokens[1]);
+ break;
+ case "disallowReferenceUriSchemes":
+ if (tokens.length == 1) {
+ error(entry);
+ }
+ for (int i = 1; i < tokens.length; i++) {
+ String scheme = tokens[i];
+ disallowedRefUriSchemes.add(
+ scheme.toLowerCase(Locale.ROOT));
+ }
+ break;
+ case "minKeySize":
+ if (tokens.length != 3) {
+ error(entry);
+ }
+ minKeyMap.put(tokens[1],
+ Integer.parseUnsignedInt(tokens[2]));
+ break;
+ case "noDuplicateIds":
+ if (tokens.length != 1) {
+ error(entry);
+ }
+ noDuplicateIds = true;
+ break;
+ case "noRetrievalMethodLoops":
+ if (tokens.length != 1) {
+ error(entry);
+ }
+ noRMLoops = true;
+ break;
+ default:
+ error(entry);
+ }
+ }
+ }
+
+ public static boolean restrictAlg(String alg) {
+ try {
+ URI uri = new URI(alg);
+ return disallowedAlgs.contains(uri);
+ } catch (URISyntaxException use) {
+ return false;
+ }
+ }
+
+ public static boolean restrictNumTransforms(int numTrans) {
+ return (numTrans > maxTrans);
+ }
+
+ public static boolean restrictNumReferences(int numRefs) {
+ return (numRefs > maxRefs);
+ }
+
+ public static boolean restrictReferenceUriScheme(String uri) {
+ if (uri != null) {
+ String scheme = java.net.URI.create(uri).getScheme();
+ if (scheme != null) {
+ return disallowedRefUriSchemes.contains(
+ scheme.toLowerCase(Locale.ROOT));
+ }
+ }
+ return false;
+ }
+
+ public static boolean restrictKey(String type, int size) {
+ return (size < minKeyMap.getOrDefault(type, 0));
+ }
+
+ public static boolean restrictDuplicateIds() {
+ return noDuplicateIds;
+ }
+
+ public static boolean restrictRetrievalMethodLoops() {
+ return noRMLoops;
+ }
+
+ public static Set<URI> disabledAlgs() {
+ return Collections.<URI>unmodifiableSet(disallowedAlgs);
+ }
+
+ public static int maxTransforms() {
+ return maxTrans;
+ }
+
+ public static int maxReferences() {
+ return maxRefs;
+ }
+
+ public static Set<String> disabledReferenceUriSchemes() {
+ return Collections.<String>unmodifiableSet(disallowedRefUriSchemes);
+ }
+
+ public static int minKeySize(String type) {
+ return minKeyMap.getOrDefault(type, 0);
+ }
+
+ private static void error(String entry) {
+ throw new IllegalArgumentException(
+ "Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry);
+ }
+}
diff --git a/openjdk/jdk/src/share/classes/sun/awt/AWTAccessor.java b/openjdk/jdk/src/share/classes/sun/awt/AWTAccessor.java
index d491ebe..c5ac08a 100644
--- openjdk/jdk/src/share/classes/sun/awt/AWTAccessor.java
+++ openjdk/jdk/src/share/classes/sun/awt/AWTAccessor.java
@@ -36,6 +36,7 @@ import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.awt.peer.ComponentPeer;
+import java.awt.peer.MenuComponentPeer;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext;
@@ -463,6 +464,11 @@ public final class AWTAccessor {
* Gets the font used for this menu component.
*/
Font getFont_NoClientCode(MenuComponent menuComp);
+
+ /**
+ * Returns the peer of the menu component.
+ */
+ <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp);
}
/**
diff --git a/openjdk/jdk/src/share/classes/sun/misc/JarIndex.java b/openjdk/jdk/src/share/classes/sun/misc/JarIndex.java
index e43b9ee..6e08cf2 100644
--- openjdk/jdk/src/share/classes/sun/misc/JarIndex.java
+++ openjdk/jdk/src/share/classes/sun/misc/JarIndex.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,11 @@
package sun.misc;
import java.io.*;
+import java.security.AccessController;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
+import sun.security.action.GetPropertyAction;
/**
* This class is used to maintain mappings from packages, classes
@@ -72,7 +74,8 @@ public class JarIndex {
* be added to the index. Otherwise, just the directory names are added.
*/
private static final boolean metaInfFilenames =
- "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames"));
+ "true".equals(AccessController.doPrivileged(
+ new GetPropertyAction("sun.misc.JarIndex.metaInfFilenames")));
/**
* Constructs a new, empty jar index.
diff --git a/openjdk/jdk/src/share/classes/sun/misc/JavaOISAccess.java b/openjdk/jdk/src/share/classes/sun/misc/JavaOISAccess.java
new file mode 100644
index 0000000..8be96eb
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/misc/JavaOISAccess.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.io.ObjectInputStream;
+
+public interface JavaOISAccess {
+ void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter);
+ ObjectInputFilter getObjectInputFilter(ObjectInputStream stream);
+}
diff --git a/openjdk/jdk/src/share/classes/sun/misc/Launcher.java b/openjdk/jdk/src/share/classes/sun/misc/Launcher.java
index f72f60e..0f33139 100644
--- openjdk/jdk/src/share/classes/sun/misc/Launcher.java
+++ openjdk/jdk/src/share/classes/sun/misc/Launcher.java
@@ -408,7 +408,7 @@ public class Launcher {
} else {
urls = new URL[0];
}
- bcp = new URLClassPath(urls, factory);
+ bcp = new URLClassPath(urls, factory, null);
bcp.initLookupCache(null);
}
}
diff --git a/openjdk/jdk/src/share/classes/sun/misc/ObjectInputFilter.java b/openjdk/jdk/src/share/classes/sun/misc/ObjectInputFilter.java
new file mode 100644
index 0000000..467f7b7
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/misc/ObjectInputFilter.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.io.ObjectInputStream;
+import java.io.SerializablePermission;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * Filter classes, array lengths, and graph metrics during deserialization.
+ * If set on an {@link ObjectInputStream}, the {@link #checkInput checkInput(FilterInfo)}
+ * method is called to validate classes, the length of each array,
+ * the number of objects being read from the stream, the depth of the graph,
+ * and the total number of bytes read from the stream.
+ * <p>
+ * A filter can be set via {@link ObjectInputStream#setObjectInputFilter setObjectInputFilter}
+ * for an individual ObjectInputStream.
+ * A filter can be set via {@link Config#setSerialFilter(ObjectInputFilter) Config.setSerialFilter}
+ * to affect every {@code ObjectInputStream} that does not otherwise set a filter.
+ * <p>
+ * A filter determines whether the arguments are {@link Status#ALLOWED ALLOWED}
+ * or {@link Status#REJECTED REJECTED} and should return the appropriate status.
+ * If the filter cannot determine the status it should return
+ * {@link Status#UNDECIDED UNDECIDED}.
+ * Filters should be designed for the specific use case and expected types.
+ * A filter designed for a particular use may be passed a class that is outside
+ * of the scope of the filter. If the purpose of the filter is to black-list classes
+ * then it can reject a candidate class that matches and report UNDECIDED for others.
+ * A filter may be called with class equals {@code null}, {@code arrayLength} equal -1,
+ * the depth, number of references, and stream size and return a status
+ * that reflects only one or only some of the values.
+ * This allows a filter to specific about the choice it is reporting and
+ * to use other filters without forcing either allowed or rejected status.
+ *
+ * <p>
+ * Typically, a custom filter should check if a process-wide filter
+ * is configured and defer to it if so. For example,
+ * <pre>{@code
+ * ObjectInputFilter.Status checkInput(FilterInfo info) {
+ * ObjectInputFilter serialFilter = ObjectInputFilter.Config.getSerialFilter();
+ * if (serialFilter != null) {
+ * ObjectInputFilter.Status status = serialFilter.checkInput(info);
+ * if (status != ObjectInputFilter.Status.UNDECIDED) {
+ * // The process-wide filter overrides this filter
+ * return status;
+ * }
+ * }
+ * if (info.serialClass() != null &&
+ * Remote.class.isAssignableFrom(info.serialClass())) {
+ * return Status.REJECTED; // Do not allow Remote objects
+ * }
+ * return Status.UNDECIDED;
+ * }
+ *}</pre>
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a
+ * method in this interface and its nested classes will cause a
+ * {@link NullPointerException} to be thrown.
+ *
+ * @since 8u
+ */
+@FunctionalInterface
+public interface ObjectInputFilter {
+
+ /**
+ * Check the class, array length, number of object references, depth,
+ * stream size, and other available filtering information.
+ * Implementations of this method check the contents of the object graph being created
+ * during deserialization. The filter returns {@link Status#ALLOWED Status.ALLOWED},
+ * {@link Status#REJECTED Status.REJECTED}, or {@link Status#UNDECIDED Status.UNDECIDED}.
+ *
+ * @param filterInfo provides information about the current object being deserialized,
+ * if any, and the status of the {@link ObjectInputStream}
+ * @return {@link Status#ALLOWED Status.ALLOWED} if accepted,
+ * {@link Status#REJECTED Status.REJECTED} if rejected,
+ * {@link Status#UNDECIDED Status.UNDECIDED} if undecided.
+ */
+ Status checkInput(FilterInfo filterInfo);
+
+ /**
+ * FilterInfo provides access to information about the current object
+ * being deserialized and the status of the {@link ObjectInputStream}.
+ * @since 9
+ */
+ interface FilterInfo {
+ /**
+ * The class of an object being deserialized.
+ * For arrays, it is the array type.
+ * For example, the array class name of a 2 dimensional array of strings is
+ * "{@code [[Ljava.lang.String;}".
+ * To check the array's element type, iteratively use
+ * {@link Class#getComponentType() Class.getComponentType} while the result
+ * is an array and then check the class.
+ * The {@code serialClass is null} in the case where a new object is not being
+ * created and to give the filter a chance to check the depth, number of
+ * references to existing objects, and the stream size.
+ *
+ * @return class of an object being deserialized; may be null
+ */
+ Class<?> serialClass();
+
+ /**
+ * The number of array elements when deserializing an array of the class.
+ *
+ * @return the non-negative number of array elements when deserializing
+ * an array of the class, otherwise -1
+ */
+ long arrayLength();
+
+ /**
+ * The current depth.
+ * The depth starts at {@code 1} and increases for each nested object and
+ * decrements when each nested object returns.
+ *
+ * @return the current depth
+ */
+ long depth();
+
+ /**
+ * The current number of object references.
+ *
+ * @return the non-negative current number of object references
+ */
+ long references();
+
+ /**
+ * The current number of bytes consumed.
+ * @implSpec {@code streamBytes} is implementation specific
+ * and may not be directly related to the object in the stream
+ * that caused the callback.
+ *
+ * @return the non-negative current number of bytes consumed
+ */
+ long streamBytes();
+ }
+
+ /**
+ * The status of a check on the class, array length, number of references,
+ * depth, and stream size.
+ *
+ * @since 8u
+ */
+ enum Status {
+ /**
+ * The status is undecided, not allowed and not rejected.
+ */
+ UNDECIDED,
+ /**
+ * The status is allowed.
+ */
+ ALLOWED,
+ /**
+ * The status is rejected.
+ */
+ REJECTED;
+ }
+
+ /**
+ * A utility class to set and get the process-wide filter or create a filter
+ * from a pattern string. If a process-wide filter is set, it will be
+ * used for each {@link ObjectInputStream} that does not set its own filter.
+ * <p>
+ * When setting the filter, it should be stateless and idempotent,
+ * reporting the same result when passed the same arguments.
+ * <p>
+ * The filter is configured using the {@link java.security.Security}
+ * property {@code jdk.serialFilter} and can be overridden by
+ * the System property {@code jdk.serialFilter}.
+ *
+ * The syntax is the same as for the {@link #createFilter(String) createFilter} method.
+ *
+ * @since 8u
+ */
+ final class Config {
+ /* No instances. */
+ private Config() {}
+
+ /**
+ * Lock object for process-wide filter.
+ */
+ private final static Object serialFilterLock = new Object();
+
+ /**
+ * Debug: Logger
+ */
+ private final static PlatformLogger configLog;
+
+ /**
+ * Logger for debugging.
+ */
+ static void filterLog(PlatformLogger.Level level, String msg, Object... args) {
+ if (configLog != null) {
+ if (PlatformLogger.Level.INFO.equals(level)) {
+ configLog.info(msg, args);
+ } else if (PlatformLogger.Level.WARNING.equals(level)) {
+ configLog.warning(msg, args);
+ } else {
+ configLog.severe(msg, args);
+ }
+ }
+ }
+
+ /**
+ * The name for the process-wide deserialization filter.
+ * Used as a system property and a java.security.Security property.
+ */
+ private final static String SERIAL_FILTER_PROPNAME = "jdk.serialFilter";
+
+ /**
+ * The process-wide filter; may be null.
+ * Lookup the filter in java.security.Security or
+ * the system property.
+ */
+ private final static ObjectInputFilter configuredFilter;
+
+ static {
+ configuredFilter = AccessController
+ .doPrivileged((PrivilegedAction<ObjectInputFilter>) () -> {
+ String props = System.getProperty(SERIAL_FILTER_PROPNAME);
+ if (props == null) {
+ props = Security.getProperty(SERIAL_FILTER_PROPNAME);
+ }
+ if (props != null) {
+ PlatformLogger log = PlatformLogger.getLogger("java.io.serialization");
+ log.info("Creating serialization filter from {0}", props);
+ try {
+ return createFilter(props);
+ } catch (RuntimeException re) {
+ log.warning("Error configuring filter: {0}", re);
+ }
+ }
+ return null;
+ });
+ configLog = (configuredFilter != null) ? PlatformLogger.getLogger("java.io.serialization") : null;
+ }
+
+ /**
+ * Current configured filter.
+ */
+ private static ObjectInputFilter serialFilter = configuredFilter;
+
+ /**
+ * Get the filter for classes being deserialized on the ObjectInputStream.
+ *
+ * @param inputStream ObjectInputStream from which to get the filter; non-null
+ * @throws RuntimeException if the filter rejects
+ */
+ public static ObjectInputFilter getObjectInputFilter(ObjectInputStream inputStream) {
+ Objects.requireNonNull(inputStream, "inputStream");
+ return sun.misc.SharedSecrets.getJavaOISAccess().getObjectInputFilter(inputStream);
+ }
+
+ /**
+ * Set the process-wide filter if it has not already been configured or set.
+ *
+ * @param inputStream ObjectInputStream on which to set the filter; non-null
+ * @param filter the serialization filter to set as the process-wide filter; not null
+ * @throws SecurityException if there is security manager and the
+ * {@code SerializablePermission("serialFilter")} is not granted
+ * @throws IllegalStateException if the filter has already been set {@code non-null}
+ */
+ public static void setObjectInputFilter(ObjectInputStream inputStream,
+ ObjectInputFilter filter) {
+ Objects.requireNonNull(inputStream, "inputStream");
+ sun.misc.SharedSecrets.getJavaOISAccess().setObjectInputFilter(inputStream, filter);
+ }
+
+ /**
+ * Returns the process-wide serialization filter or {@code null} if not configured.
+ *
+ * @return the process-wide serialization filter or {@code null} if not configured
+ */
+ public static ObjectInputFilter getSerialFilter() {
+ synchronized (serialFilterLock) {
+ return serialFilter;
+ }
+ }
+
+ /**
+ * Set the process-wide filter if it has not already been configured or set.
+ *
+ * @param filter the serialization filter to set as the process-wide filter; not null
+ * @throws SecurityException if there is security manager and the
+ * {@code SerializablePermission("serialFilter")} is not granted
+ * @throws IllegalStateException if the filter has already been set {@code non-null}
+ */
+ public static void setSerialFilter(ObjectInputFilter filter) {
+ Objects.requireNonNull(filter, "filter");
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new SerializablePermission("serialFilter"));
+ }
+ synchronized (serialFilterLock) {
+ if (serialFilter != null) {
+ throw new IllegalStateException("Serial filter can only be set once");
+ }
+ serialFilter = filter;
+ }
+ }
+
+ /**
+ * Returns an ObjectInputFilter from a string of patterns.
+ * <p>
+ * Patterns are separated by ";" (semicolon). Whitespace is significant and
+ * is considered part of the pattern.
+ * If a pattern includes an equals assignment, "{@code =}" it sets a limit.
+ * If a limit appears more than once the last value is used.
+ * <ul>
+ * <li>maxdepth={@code value} - the maximum depth of a graph</li>
+ * <li>maxrefs={@code value} - the maximum number of internal references</li>
+ * <li>maxbytes={@code value} - the maximum number of bytes in the input stream</li>
+ * <li>maxarray={@code value} - the maximum array length allowed</li>
+ * </ul>
+ * <p>
+ * Other patterns match or reject class or package name
+ * as returned from {@link Class#getName() Class.getName()}.
+ * Note that for arrays the element type is used in the pattern,
+ * not the array type.
+ * <ul>
+ * <li>If the pattern starts with "!", the class is rejected if the remaining pattern is matched;
+ * otherwise the class is allowed if the pattern matches.
+ * <li>If the pattern ends with ".**" it matches any class in the package and all subpackages.
+ * <li>If the pattern ends with ".*" it matches any class in the package.
+ * <li>If the pattern ends with "*", it matches any class with the pattern as a prefix.
+ * <li>If the pattern is equal to the class name, it matches.
+ * <li>Otherwise, the pattern is not matched.
+ * </ul>
+ * <p>
+ * The resulting filter performs the limit checks and then
+ * tries to match the class, if any. If any of the limits are exceeded,
+ * the filter returns {@link Status#REJECTED Status.REJECTED}.
+ * If the class is an array type, the class to be matched is the element type.
+ * Arrays of any number of dimensions are treated the same as the element type.
+ * For example, a pattern of "{@code !example.Foo}",
+ * rejects creation of any instance or array of {@code example.Foo}.
+ * The first pattern that matches, working from left to right, determines
+ * the {@link Status#ALLOWED Status.ALLOWED}
+ * or {@link Status#REJECTED Status.REJECTED} result.
+ * If nothing matches, the result is {@link Status#UNDECIDED Status.UNDECIDED}.
+ *
+ * @param pattern the pattern string to parse; not null
+ * @return a filter to check a class being deserialized; may be null;
+ * {@code null} if no patterns
+ * @throws IllegalArgumentException
+ * if a limit is missing the name, or the long value
+ * is not a number or is negative,
+ * or if the package is missing for ".*" and ".**"
+ */
+ public static ObjectInputFilter createFilter(String pattern) {
+ Objects.requireNonNull(pattern, "pattern");
+ return Global.createFilter(pattern);
+ }
+
+ /**
+ * Implementation of ObjectInputFilter that performs the checks of
+ * the process-wide serialization filter. If configured, it will be
+ * used for all ObjectInputStreams that do not set their own filters.
+ *
+ */
+ final static class Global implements ObjectInputFilter {
+ /**
+ * The pattern used to create the filter.
+ */
+ private final String pattern;
+ /**
+ * The list of class filters.
+ */
+ private final List<Function<Class<?>, Status>> filters;
+ /**
+ * Maximum allowed bytes in the stream.
+ */
+ private long maxStreamBytes;
+ /**
+ * Maximum depth of the graph allowed.
+ */
+ private long maxDepth;
+ /**
+ * Maximum number of references in a graph.
+ */
+ private long maxReferences;
+ /**
+ * Maximum length of any array.
+ */
+ private long maxArrayLength;
+
+ /**
+ * Returns an ObjectInputFilter from a string of patterns.
+ *
+ * @param pattern the pattern string to parse
+ * @return a filter to check a class being deserialized; not null
+ * @throws IllegalArgumentException if the parameter is malformed
+ * if the pattern is missing the name, the long value
+ * is not a number or is negative.
+ */
+ static ObjectInputFilter createFilter(String pattern) {
+ Global filter = new Global(pattern);
+ return filter.isEmpty() ? null : filter;
+ }
+
+ /**
+ * Construct a new filter from the pattern String.
+ *
+ * @param pattern a pattern string of filters
+ * @throws IllegalArgumentException if the pattern is malformed
+ */
+ private Global(String pattern) {
+ this.pattern = pattern;
+
+ maxArrayLength = Long.MAX_VALUE; // Default values are unlimited
+ maxDepth = Long.MAX_VALUE;
+ maxReferences = Long.MAX_VALUE;
+ maxStreamBytes = Long.MAX_VALUE;
+
+ String[] patterns = pattern.split(";");
+ filters = new ArrayList<>(patterns.length);
+ for (int i = 0; i < patterns.length; i++) {
+ String p = patterns[i];
+ int nameLen = p.length();
+ if (nameLen == 0) {
+ continue;
+ }
+ if (parseLimit(p)) {
+ // If the pattern contained a limit setting, i.e. type=value
+ continue;
+ }
+ boolean negate = p.charAt(0) == '!';
+
+ if (p.indexOf('/') >= 0) {
+ throw new IllegalArgumentException("invalid character \"/\" in: \"" + pattern + "\"");
+ }
+
+ if (p.endsWith("*")) {
+ // Wildcard cases
+ if (p.endsWith(".*")) {
+ // Pattern is a package name with a wildcard
+ final String pkg = p.substring(negate ? 1 : 0, nameLen - 1);
+ if (pkg.length() < 2) {
+ throw new IllegalArgumentException("package missing in: \"" + pattern + "\"");
+ }
+ if (negate) {
+ // A Function that fails if the class starts with the pattern, otherwise don't care
+ filters.add(c -> matchesPackage(c, pkg) ? Status.REJECTED : Status.UNDECIDED);
+ } else {
+ // A Function that succeeds if the class starts with the pattern, otherwise don't care
+ filters.add(c -> matchesPackage(c, pkg) ? Status.ALLOWED : Status.UNDECIDED);
+ }
+ } else if (p.endsWith(".**")) {
+ // Pattern is a package prefix with a double wildcard
+ final String pkgs = p.substring(negate ? 1 : 0, nameLen - 2);
+ if (pkgs.length() < 2) {
+ throw new IllegalArgumentException("package missing in: \"" + pattern + "\"");
+ }
+ if (negate) {
+ // A Function that fails if the class starts with the pattern, otherwise don't care
+ filters.add(c -> c.getName().startsWith(pkgs) ? Status.REJECTED : Status.UNDECIDED);
+ } else {
+ // A Function that succeeds if the class starts with the pattern, otherwise don't care
+ filters.add(c -> c.getName().startsWith(pkgs) ? Status.ALLOWED : Status.UNDECIDED);
+ }
+ } else {
+ // Pattern is a classname (possibly empty) with a trailing wildcard
+ final String className = p.substring(negate ? 1 : 0, nameLen - 1);
+ if (negate) {
+ // A Function that fails if the class starts with the pattern, otherwise don't care
+ filters.add(c -> c.getName().startsWith(className) ? Status.REJECTED : Status.UNDECIDED);
+ } else {
+ // A Function that succeeds if the class starts with the pattern, otherwise don't care
+ filters.add(c -> c.getName().startsWith(className) ? Status.ALLOWED : Status.UNDECIDED);
+ }
+ }
+ } else {
+ final String name = p.substring(negate ? 1 : 0);
+ if (name.isEmpty()) {
+ throw new IllegalArgumentException("class or package missing in: \"" + pattern + "\"");
+ }
+ // Pattern is a class name
+ if (negate) {
+ // A Function that fails if the class equals the pattern, otherwise don't care
+ filters.add(c -> c.getName().equals(name) ? Status.REJECTED : Status.UNDECIDED);
+ } else {
+ // A Function that succeeds if the class equals the pattern, otherwise don't care
+ filters.add(c -> c.getName().equals(name) ? Status.ALLOWED : Status.UNDECIDED);
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Returns if this filter has any checks.
+ * @return {@code true} if the filter has any checks, {@code false} otherwise
+ */
+ private boolean isEmpty() {
+ return filters.isEmpty() &&
+ maxArrayLength == Long.MAX_VALUE &&
+ maxDepth == Long.MAX_VALUE &&
+ maxReferences == Long.MAX_VALUE &&
+ maxStreamBytes == Long.MAX_VALUE;
+ }
+
+ /**
+ * Parse out a limit for one of maxarray, maxdepth, maxbytes, maxreferences.
+ *
+ * @param pattern a string with a type name, '=' and a value
+ * @return {@code true} if a limit was parsed, else {@code false}
+ * @throws IllegalArgumentException if the pattern is missing
+ * the name, the Long value is not a number or is negative.
+ */
+ private boolean parseLimit(String pattern) {
+ int eqNdx = pattern.indexOf('=');
+ if (eqNdx < 0) {
+ // not a limit pattern
+ return false;
+ }
+ String valueString = pattern.substring(eqNdx + 1);
+ if (pattern.startsWith("maxdepth=")) {
+ maxDepth = parseValue(valueString);
+ } else if (pattern.startsWith("maxarray=")) {
+ maxArrayLength = parseValue(valueString);
+ } else if (pattern.startsWith("maxrefs=")) {
+ maxReferences = parseValue(valueString);
+ } else if (pattern.startsWith("maxbytes=")) {
+ maxStreamBytes = parseValue(valueString);
+ } else {
+ throw new IllegalArgumentException("unknown limit: " + pattern.substring(0, eqNdx));
+ }
+ return true;
+ }
+
+ /**
+ * Parse the value of a limit and check that it is non-negative.
+ * @param string inputstring
+ * @return the parsed value
+ * @throws IllegalArgumentException if parsing the value fails or the value is negative
+ */
+ private static long parseValue(String string) throws IllegalArgumentException {
+ // Parse a Long from after the '=' to the end
+ long value = Long.parseLong(string);
+ if (value < 0) {
+ throw new IllegalArgumentException("negative limit: " + string);
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Status checkInput(FilterInfo filterInfo) {
+ if (filterInfo.references() < 0
+ || filterInfo.depth() < 0
+ || filterInfo.streamBytes() < 0
+ || filterInfo.references() > maxReferences
+ || filterInfo.depth() > maxDepth
+ || filterInfo.streamBytes() > maxStreamBytes) {
+ return Status.REJECTED;
+ }
+
+ Class<?> clazz = filterInfo.serialClass();
+ if (clazz != null) {
+ if (clazz.isArray()) {
+ if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > maxArrayLength) {
+ // array length is too big
+ return Status.REJECTED;
+ }
+ do {
+ // Arrays are decided based on the component type
+ clazz = clazz.getComponentType();
+ } while (clazz.isArray());
+ }
+
+ if (clazz.isPrimitive()) {
+ // Primitive types are undecided; let someone else decide
+ return Status.UNDECIDED;
+ } else {
+ // Find any filter that allowed or rejected the class
+ final Class<?> cl = clazz;
+ Optional<Status> status = filters.stream()
+ .map(f -> f.apply(cl))
+ .filter(p -> p != Status.UNDECIDED)
+ .findFirst();
+ return status.orElse(Status.UNDECIDED);
+ }
+ }
+ return Status.UNDECIDED;
+ }
+
+ /**
+ * Returns {@code true} if the class is in the package.
+ *
+ * @param c a class
+ * @param pkg a package name (including the trailing ".")
+ * @return {@code true} if the class is in the package,
+ * otherwise {@code false}
+ */
+ private static boolean matchesPackage(Class<?> c, String pkg) {
+ String n = c.getName();
+ return n.startsWith(pkg) && n.lastIndexOf('.') == pkg.length() - 1;
+ }
+
+ /**
+ * Returns the pattern used to create this filter.
+ * @return the pattern used to create this filter
+ */
+ @Override
+ public String toString() {
+ return pattern;
+ }
+ }
+ }
+}
diff --git a/openjdk/jdk/src/share/classes/sun/misc/SharedSecrets.java b/openjdk/jdk/src/share/classes/sun/misc/SharedSecrets.java
index 2f995da..3539962 100644
--- openjdk/jdk/src/share/classes/sun/misc/SharedSecrets.java
+++ openjdk/jdk/src/share/classes/sun/misc/SharedSecrets.java
@@ -25,6 +25,7 @@
package sun.misc;
+import java.io.ObjectInputStream;
import java.util.jar.JarFile;
import java.io.Console;
import java.io.FileDescriptor;
@@ -56,6 +57,7 @@ public class SharedSecrets {
private static JavaSecurityAccess javaSecurityAccess;
private static JavaUtilZipFileAccess javaUtilZipFileAccess;
private static JavaAWTAccess javaAWTAccess;
+ private static JavaOISAccess javaOISAccess;
private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -141,6 +143,18 @@ public class SharedSecrets {
return javaIOFileDescriptorAccess;
}
+ public static void setJavaOISAccess(JavaOISAccess access) {
+ javaOISAccess = access;
+ }
+
+ public static JavaOISAccess getJavaOISAccess() {
+ if (javaOISAccess == null)
+ unsafe.ensureClassInitialized(ObjectInputStream.class);
+
+ return javaOISAccess;
+ }
+
+
public static void setJavaSecurityProtectionDomainAccess
(JavaSecurityProtectionDomainAccess jspda) {
javaSecurityProtectionDomainAccess = jspda;
diff --git a/openjdk/jdk/src/share/classes/sun/misc/URLClassPath.java b/openjdk/jdk/src/share/classes/sun/misc/URLClassPath.java
index f92b1de..5f56056 100644
--- openjdk/jdk/src/share/classes/sun/misc/URLClassPath.java
+++ openjdk/jdk/src/share/classes/sun/misc/URLClassPath.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@ import java.net.HttpURLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.io.*;
+import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.AccessControlException;
import java.security.CodeSigner;
@@ -67,6 +68,7 @@ public class URLClassPath {
private static final boolean DEBUG;
private static final boolean DEBUG_LOOKUP_CACHE;
private static final boolean DISABLE_JAR_CHECKING;
+ private static final boolean DISABLE_ACC_CHECKING;
static {
JAVA_VERSION = java.security.AccessController.doPrivileged(
@@ -78,6 +80,10 @@ public class URLClassPath {
String p = java.security.AccessController.doPrivileged(
new GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
+
+ p = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions"));
+ DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
/* The original search path of URLs. */
@@ -98,6 +104,11 @@ public class URLClassPath {
/* Whether this URLClassLoader has been closed yet */
private boolean closed = false;
+ /* The context to be used when loading classes and resources. If non-null
+ * this is the context that was captured during the creation of the
+ * URLClassLoader. null implies no additional security restrictions. */
+ private final AccessControlContext acc;
+
/**
* Creates a new URLClassPath for the given URLs. The URLs will be
* searched in the order specified for classes and resources. A URL
@@ -107,8 +118,12 @@ public class URLClassPath {
* @param urls the directory and JAR file URLs to search for classes
* and resources
* @param factory the URLStreamHandlerFactory to use when creating new URLs
+ * @param acc the context to be used when loading classes and resources, may
+ * be null
*/
- public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
+ public URLClassPath(URL[] urls,
+ URLStreamHandlerFactory factory,
+ AccessControlContext acc) {
for (int i = 0; i < urls.length; i++) {
path.add(urls[i]);
}
@@ -116,10 +131,22 @@ public class URLClassPath {
if (factory != null) {
jarHandler = factory.createURLStreamHandler("jar");
}
+ if (DISABLE_ACC_CHECKING)
+ this.acc = null;
+ else
+ this.acc = acc;
}
+ /**
+ * Constructs a URLClassPath with no additional security restrictions.
+ * Used by code that implements the class path.
+ */
public URLClassPath(URL[] urls) {
- this(urls, null);
+ this(urls, null, null);
+ }
+
+ public URLClassPath(URL[] urls, AccessControlContext acc) {
+ this(urls, null, acc);
}
public synchronized List<IOException> closeLoaders() {
@@ -499,6 +526,14 @@ public class URLClassPath {
} catch (IOException e) {
// Silently ignore for now...
continue;
+ } catch (SecurityException se) {
+ // Always silently ignore. The context, if there is one, that
+ // this URLClassPath was given during construction will never
+ // have permission to access the URL.
+ if (DEBUG) {
+ System.err.println("Failed to access " + url + ", " + se );
+ }
+ continue;
}
// Finally, add the Loader to the search path.
validateLookupCache(loaders.size(), urlNoFragString);
@@ -527,10 +562,10 @@ public class URLClassPath {
return new Loader(url);
}
} else {
- return new JarLoader(url, jarHandler, lmap);
+ return new JarLoader(url, jarHandler, lmap, acc);
}
}
- });
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -755,11 +790,12 @@ public class URLClassPath {
*/
static class JarLoader extends Loader {
private JarFile jar;
- private URL csu;
+ private final URL csu;
private JarIndex index;
private MetaIndex metaIndex;
private URLStreamHandler handler;
- private HashMap<String, Loader> lmap;
+ private final HashMap<String, Loader> lmap;
+ private final AccessControlContext acc;
private boolean closed = false;
private static final sun.misc.JavaUtilZipFileAccess zipAccess =
sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
@@ -769,13 +805,15 @@ public class URLClassPath {
* a JAR file.
*/
JarLoader(URL url, URLStreamHandler jarHandler,
- HashMap<String, Loader> loaderMap)
+ HashMap<String, Loader> loaderMap,
+ AccessControlContext acc)
throws IOException
{
super(new URL("jar", "", -1, url + "!/", jarHandler));
csu = url;
handler = jarHandler;
lmap = loaderMap;
+ this.acc = acc;
if (!isOptimizable(url)) {
ensureOpen();
@@ -859,8 +897,7 @@ public class URLClassPath {
}
return null;
}
- }
- );
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -1054,9 +1091,9 @@ public class URLClassPath {
new PrivilegedExceptionAction<JarLoader>() {
public JarLoader run() throws IOException {
return new JarLoader(url, handler,
- lmap);
+ lmap, acc);
}
- });
+ }, acc);
/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
diff --git a/openjdk/jdk/src/share/classes/sun/reflect/ReflectionFactory.java b/openjdk/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
index dc26fab..95408bd 100644
--- openjdk/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
+++ openjdk/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
@@ -25,16 +25,28 @@
package sun.reflect;
+import java.io.Externalizable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
+import java.util.Objects;
+
import sun.reflect.misc.ReflectUtil;
+
/** <P> The master factory for all reflective objects, both those in
java.lang.reflect (Fields, Methods, Constructors) as well as their
delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
@@ -56,6 +68,9 @@ public class ReflectionFactory {
// Provides access to package-private mechanisms in java.lang.reflect
private static volatile LangReflectAccess langReflectAccess;
+ /* Method for static class initializer <clinit>, or null */
+ private static volatile Method hasStaticInitializerMethod;
+
//
// "Inflation" mechanism. Loading bytecodes to implement
// Method.invoke() and Constructor.newInstance() currently costs
@@ -73,8 +88,7 @@ public class ReflectionFactory {
private static boolean noInflation = false;
private static int inflationThreshold = 15;
- private ReflectionFactory() {
- }
+ private ReflectionFactory() {}
/**
* A convenience class for acquiring the capability to instantiate
@@ -328,6 +342,14 @@ public class ReflectionFactory {
//
//
+ /**
+ * Returns an accessible constructor capable of creating instances
+ * of the given class, initialized by the given constructor.
+ *
+ * @param classToInstantiate the class to instantiate
+ * @param constructorToCall the constructor to call
+ * @return an accessible constructor
+ */
public Constructor<?> newConstructorForSerialization
(Class<?> classToInstantiate, Constructor<?> constructorToCall)
{
@@ -335,6 +357,42 @@ public class ReflectionFactory {
if (constructorToCall.getDeclaringClass() == classToInstantiate) {
return constructorToCall;
}
+ return generateConstructor(classToInstantiate, constructorToCall);
+ }
+
+ /**
+ * Returns an accessible no-arg constructor for a class.
+ * The no-arg constructor is found searching the class and its supertypes.
+ *
+ * @param cl the class to instantiate
+ * @return a no-arg constructor for the class or {@code null} if
+ * the class or supertypes do not have a suitable no-arg constructor
+ */
+ public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
+ Class<?> initCl = cl;
+ while (Serializable.class.isAssignableFrom(initCl)) {
+ if ((initCl = initCl.getSuperclass()) == null) {
+ return null;
+ }
+ }
+ Constructor<?> constructorToCall;
+ try {
+ constructorToCall = initCl.getDeclaredConstructor();
+ int mods = constructorToCall.getModifiers();
+ if ((mods & Modifier.PRIVATE) != 0 ||
+ ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
+ !packageEquals(cl, initCl))) {
+ return null;
+ }
+ } catch (NoSuchMethodException ex) {
+ return null;
+ }
+ return generateConstructor(cl, constructorToCall);
+ }
+
+ private final Constructor<?> generateConstructor(Class<?> classToInstantiate,
+ Constructor<?> constructorToCall) {
+
ConstructorAccessor acc = new MethodAccessorGenerator().
generateSerializationConstructor(classToInstantiate,
@@ -355,9 +413,222 @@ public class ReflectionFactory {
langReflectAccess().
getConstructorParameterAnnotations(constructorToCall));
setConstructorAccessor(c, acc);
+ c.setAccessible(true);
return c;
}
+ /**
+ * Returns an accessible no-arg constructor for an externalizable class to be
+ * initialized using a public no-argument constructor.
+ *
+ * @param cl the class to instantiate
+ * @return A no-arg constructor for the class; returns {@code null} if
+ * the class does not implement {@link java.io.Externalizable}
+ */
+ public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+ if (!Externalizable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+ try {
+ Constructor<?> cons = cl.getConstructor();
+ cons.setAccessible(true);
+ return cons;
+ } catch (NoSuchMethodException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readObject} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectInputStream} passed to
+ * {@code readObject}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code readObject} method of the class or
+ * {@code null} if the class does not have a {@code readObject} method
+ */
+ public final MethodHandle readObjectForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readObjectNoData} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectInputStream} passed to
+ * {@code readObjectNoData}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code readObjectNoData} method
+ * of the class or {@code null} if the class does not have a
+ * {@code readObjectNoData} method
+ */
+ public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeObject} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectOutputStream} passed to
+ * {@code writeObject}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code writeObject} method of the class or
+ * {@code null} if the class does not have a {@code writeObject} method
+ */
+ public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
+ }
+
+ private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
+ String methodName,
+ Class<?> streamClass) {
+ if (!Serializable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+
+ try {
+ Method meth = cl.getDeclaredMethod(methodName, streamClass);
+ int mods = meth.getModifiers();
+ if (meth.getReturnType() != Void.TYPE ||
+ Modifier.isStatic(mods) ||
+ !Modifier.isPrivate(mods)) {
+ return null;
+ }
+ meth.setAccessible(true);
+ return MethodHandles.lookup().unreflect(meth);
+ } catch (NoSuchMethodException ex) {
+ return null;
+ } catch (IllegalAccessException ex1) {
+ throw new InternalError("Error", ex1);
+ }
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readResolve} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code readResolve} method of the class or
+ * {@code null} if the class does not have a {@code readResolve} method
+ */
+ public final MethodHandle readResolveForSerialization(Class<?> cl) {
+ return getReplaceResolveForSerialization(cl, "readResolve");
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeReplace} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code writeReplace} method of the class or
+ * {@code null} if the class does not have a {@code writeReplace} method
+ */
+ public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+ return getReplaceResolveForSerialization(cl, "writeReplace");
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeReplace} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code writeReplace} method of the class or
+ * {@code null} if the class does not have a {@code writeReplace} method
+ */
+ private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
+ String methodName) {
+ if (!Serializable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+
+ Class<?> defCl = cl;
+ while (defCl != null) {
+ try {
+ Method m = defCl.getDeclaredMethod(methodName);
+ if (m.getReturnType() != Object.class) {
+ return null;
+ }
+ int mods = m.getModifiers();
+ if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
+ return null;
+ } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
+ // fall through
+ } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
+ return null;
+ } else if (!packageEquals(cl, defCl)) {
+ return null;
+ }
+ try {
+ // Normal return
+ m.setAccessible(true);
+ return MethodHandles.lookup().unreflect(m);
+ } catch (IllegalAccessException ex0) {
+ // setAccessible should prevent IAE
+ throw new InternalError("Error", ex0);
+ }
+ } catch (NoSuchMethodException ex) {
+ defCl = defCl.getSuperclass();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the class has a static initializer.
+ * The presence of a static initializer is used to compute the serialVersionUID.
+ * @param cl a serializable classLook
+ * @return {@code true} if the class has a static initializer,
+ * otherwise {@code false}
+ */
+ public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+ Method m = hasStaticInitializerMethod;
+ if (m == null) {
+ try {
+ m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
+ new Class<?>[]{Class.class});
+ m.setAccessible(true);
+ hasStaticInitializerMethod = m;
+ } catch (NoSuchMethodException ex) {
+ throw new InternalError("No such method hasStaticInitializer on "
+ + ObjectStreamClass.class, ex);
+ }
+ }
+ try {
+ return (Boolean) m.invoke(null, cl);
+ } catch (InvocationTargetException | IllegalAccessException ex) {
+ throw new InternalError("Exception invoking hasStaticInitializer", ex);
+ }
+ }
+
+ /**
+ * Returns a new OptionalDataException with {@code eof} set to {@code true}
+ * or {@code false}.
+ * @param bool the value of {@code eof} in the created OptionalDataException
+ * @return a new OptionalDataException
+ */
+ public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
+ try {
+ Constructor<OptionalDataException> boolCtor =
+ OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
+ boolCtor.setAccessible(true);
+ return boolCtor.newInstance(bool);
+ } catch (NoSuchMethodException | InstantiationException|
+ IllegalAccessException|InvocationTargetException ex) {
+ throw new InternalError("unable to create OptionalDataException", ex);
+ }
+ }
+
//--------------------------------------------------------------------------
//
// Internals only below this point
@@ -421,4 +692,17 @@ public class ReflectionFactory {
}
return langReflectAccess;
}
+
+ /**
+ * Returns true if classes are defined in the classloader and same package, false
+ * otherwise.
+ * @param cl1 a class
+ * @param cl2 another class
+ * @returns true if the two classes are in the same classloader and package
+ */
+ private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
+ return cl1.getClassLoader() == cl2.getClassLoader() &&
+ Objects.equals(cl1.getPackage(), cl2.getPackage());
+ }
+
}
diff --git a/openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java b/openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
index f828055..e23379d 100644
--- openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
+++ openjdk/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,11 +30,9 @@ import java.util.Hashtable;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.io.FilePermission;
-import java.io.IOException;
import java.net.*;
import java.rmi.*;
import java.rmi.server.ObjID;
-import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
@@ -47,14 +45,18 @@ import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.PermissionCollection;
import java.security.Permissions;
+import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.security.Security;
import java.text.MessageFormat;
-import sun.rmi.server.LoaderHandler;
+
+import sun.misc.ObjectInputFilter;
+
+import sun.rmi.runtime.Log;
+import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2;
import sun.rmi.transport.LiveRef;
-import sun.rmi.transport.ObjectTable;
-import sun.rmi.transport.Target;
/**
* A "registry" exists on every node that allows RMI connections to
@@ -86,6 +88,47 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
private static ResourceBundle resources = null;
/**
+ * Property name of the RMI Registry serial filter to augment
+ * the built-in list of allowed types.
+ * Setting the property in the {@code lib/security/java.security} file
+ * will enable the augmented filter.
+ */
+ private static final String REGISTRY_FILTER_PROPNAME = "sun.rmi.registry.registryFilter";
+
+ /** Registry max depth of remote invocations. **/
+ private static int REGISTRY_MAX_DEPTH = 5;
+
+ /** Registry maximum array size in remote invocations. **/
+ private static int REGISTRY_MAX_ARRAY_SIZE = 10000;
+
+ /**
+ * The registryFilter created from the value of the {@code "sun.rmi.registry.registryFilter"}
+ * property.
+ */
+ private static final ObjectInputFilter registryFilter =
+ AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)RegistryImpl::initRegistryFilter);
+
+ /**
+ * Initialize the registryFilter from the security properties or system property; if any
+ * @return an ObjectInputFilter, or null
+ */
+ private static ObjectInputFilter initRegistryFilter() {
+ ObjectInputFilter filter = null;
+ String props = System.getProperty(REGISTRY_FILTER_PROPNAME);
+ if (props == null) {
+ props = Security.getProperty(REGISTRY_FILTER_PROPNAME);
+ }
+ if (props != null) {
+ filter = ObjectInputFilter.Config.createFilter(props);
+ Log regLog = Log.getLog("sun.rmi.registry", "registry", -1);
+ if (regLog.isLoggable(Log.BRIEF)) {
+ regLog.log(Log.BRIEF, "registryFilter = " + filter);
+ }
+ }
+ return filter;
+ }
+
+ /**
* Construct a new RegistryImpl on the specified port with the
* given custom socket factory pair.
*/
@@ -100,7 +143,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws RemoteException {
LiveRef lref = new LiveRef(id, port, csf, ssf);
- setup(new UnicastServerRef2(lref));
+ setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
return null;
}
}, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -109,7 +152,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
}
} else {
LiveRef lref = new LiveRef(id, port, csf, ssf);
- setup(new UnicastServerRef2(lref));
+ setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
}
}
@@ -125,7 +168,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws RemoteException {
LiveRef lref = new LiveRef(id, port);
- setup(new UnicastServerRef(lref));
+ setup(new UnicastServerRef(lref, RegistryImpl::registryFilter));
return null;
}
}, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -134,7 +177,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
}
} else {
LiveRef lref = new LiveRef(id, port);
- setup(new UnicastServerRef(lref));
+ setup(new UnicastServerRef(lref, RegistryImpl::registryFilter));
}
}
@@ -155,7 +198,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
/**
* Returns the remote object for specified name in the registry.
* @exception RemoteException If remote operation failed.
- * @exception NotBound If name is not currently bound.
+ * @exception NotBoundException If name is not currently bound.
*/
public Remote lookup(String name)
throws RemoteException, NotBoundException
@@ -188,7 +231,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
/**
* Unbind the name.
* @exception RemoteException If remote operation failed.
- * @exception NotBound If name is not currently bound.
+ * @exception NotBoundException If name is not currently bound.
*/
public void unbind(String name)
throws RemoteException, NotBoundException, AccessException
@@ -333,6 +376,60 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
}
/**
+ * ObjectInputFilter to filter Registry input objects.
+ * The list of acceptable classes is limited to classes normally
+ * stored in a registry.
+ *
+ * @param filterInfo access to the class, array length, etc.
+ * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+ * {@link ObjectInputFilter.Status#REJECTED} if rejected,
+ * otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+ */
+ private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) {
+ if (registryFilter != null) {
+ ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo);
+ if (status != ObjectInputFilter.Status.UNDECIDED) {
+ // The Registry filter can override the built-in white-list
+ return status;
+ }
+ }
+
+ if (filterInfo.depth() > REGISTRY_MAX_DEPTH) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ Class<?> clazz = filterInfo.serialClass();
+ if (clazz != null) {
+ if (clazz.isArray()) {
+ if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ do {
+ // Arrays are allowed depending on the component type
+ clazz = clazz.getComponentType();
+ } while (clazz.isArray());
+ }
+ if (clazz.isPrimitive()) {
+ // Arrays of primitives are allowed
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ if (String.class == clazz
+ || java.lang.Number.class.isAssignableFrom(clazz)
+ || Remote.class.isAssignableFrom(clazz)
+ || java.lang.reflect.Proxy.class.isAssignableFrom(clazz)
+ || UnicastRef.class.isAssignableFrom(clazz)
+ || RMIClientSocketFactory.class.isAssignableFrom(clazz)
+ || RMIServerSocketFactory.class.isAssignableFrom(clazz)
+ || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz)
+ || java.rmi.server.UID.class.isAssignableFrom(clazz)) {
+ return ObjectInputFilter.Status.ALLOWED;
+ } else {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ }
+ return ObjectInputFilter.Status.UNDECIDED;
+ }
+
+ /**
* Main program to start a registry. <br>
* The port number can be specified on the command line.
*/
diff --git a/openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java b/openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java
index afb726e..66f9146 100644
--- openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java
+++ openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java
@@ -27,6 +27,7 @@ package sun.rmi.server;
import java.io.IOException;
import java.io.ObjectInput;
+import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectStreamClass;
import java.lang.reflect.InvocationTargetException;
@@ -53,8 +54,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicInteger;
+import sun.misc.ObjectInputFilter;
import sun.rmi.runtime.Log;
-import static sun.rmi.server.UnicastRef.marshalValue;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.Target;
import sun.rmi.transport.tcp.TCPTransport;
@@ -64,6 +65,10 @@ import sun.security.action.GetBooleanAction;
* UnicastServerRef implements the remote reference layer server-side
* behavior for remote objects exported with the "UnicastRef" reference
* type.
+ * If an {@link ObjectInputFilter ObjectInputFilter} is supplied it is
+ * invoked during deserialization to filter the arguments,
+ * otherwise the default filter of {@link ObjectInputStream ObjectInputStream}
+ * applies.
*
* @author Ann Wollrath
* @author Roger Riggs
@@ -106,6 +111,9 @@ public class UnicastServerRef extends UnicastRef
*/
private transient Skeleton skel;
+ // The ObjectInputFilter for checking the invocation arguments
+ private final transient ObjectInputFilter filter;
+
/** maps method hash to Method object for each remote method */
private transient Map<Long,Method> hashToMethod_Map = null;
@@ -124,16 +132,29 @@ public class UnicastServerRef extends UnicastRef
/**
* Create a new (empty) Unicast server remote reference.
+ * The filter is null to defer to the default ObjectInputStream filter, if any.
*/
public UnicastServerRef() {
+ this.filter = null;
}
/**
* Construct a Unicast server remote reference for a specified
* liveRef.
+ * The filter is null to defer to the default ObjectInputStream filter, if any.
*/
public UnicastServerRef(LiveRef ref) {
super(ref);
+ this.filter = null;
+ }
+
+ /**
+ * Construct a Unicast server remote reference for a specified
+ * liveRef and filter.
+ */
+ public UnicastServerRef(LiveRef ref, ObjectInputFilter filter) {
+ super(ref);
+ this.filter = filter;
}
/**
@@ -142,6 +163,7 @@ public class UnicastServerRef extends UnicastRef
*/
public UnicastServerRef(int port) {
super(new LiveRef(port));
+ this.filter = null;
}
/**
@@ -366,9 +388,26 @@ public class UnicastServerRef extends UnicastRef
}
}
+ /**
+ * Sets a filter for invocation arguments, if a filter has been set.
+ * Called by dispatch before the arguments are read.
+ */
protected void unmarshalCustomCallData(ObjectInput in)
- throws IOException, ClassNotFoundException
- {}
+ throws IOException, ClassNotFoundException {
+ if (filter != null &&
+ in instanceof ObjectInputStream) {
+ // Set the filter on the stream
+ ObjectInputStream ois = (ObjectInputStream) in;
+
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+ return null;
+ }
+ });
+ }
+ }
/**
* Handle server-side dispatch using the RMI 1.1 stub/skeleton
diff --git a/openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java b/openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java
index 1eb0805..d6103d7 100644
--- openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java
+++ openjdk/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java
@@ -25,12 +25,15 @@
package sun.rmi.server;
-import java.io.IOException;
+
import java.io.ObjectOutput;
-import java.rmi.*;
-import java.rmi.server.*;
-import sun.rmi.transport.*;
-import sun.rmi.transport.tcp.*;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RemoteRef;
+
+import sun.misc.ObjectInputFilter;
+
+import sun.rmi.transport.LiveRef;
/**
* Server-side ref for a remote impl that uses a custom socket factory.
@@ -59,6 +62,16 @@ public class UnicastServerRef2 extends UnicastServerRef
}
/**
+ * Construct a Unicast server remote reference for a specified
+ * liveRef and filter.
+ */
+ public UnicastServerRef2(LiveRef ref,
+ ObjectInputFilter filter)
+ {
+ super(ref, filter);
+ }
+
+ /**
* Construct a Unicast server remote reference to be exported
* on the specified port.
*/
@@ -70,6 +83,18 @@ public class UnicastServerRef2 extends UnicastServerRef
}
/**
+ * Construct a Unicast server remote reference to be exported
+ * on the specified port.
+ */
+ public UnicastServerRef2(int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf,
+ ObjectInputFilter filter)
+ {
+ super(new LiveRef(port, csf, ssf), filter);
+ }
+
+ /**
* Returns the class of the ref type to be serialized
*/
public String getRefClass(ObjectOutput out)
diff --git a/openjdk/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java b/openjdk/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java
index 7cf4bba..af1cf04 100644
--- openjdk/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java
+++ openjdk/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,11 +34,13 @@ import java.rmi.server.LogStream;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteServer;
import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UID;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.security.Security;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
@@ -49,6 +51,9 @@ import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+
+import sun.misc.ObjectInputFilter;
+
import sun.rmi.runtime.Log;
import sun.rmi.runtime.RuntimeUtil;
import sun.rmi.server.UnicastRef;
@@ -102,6 +107,45 @@ final class DGCImpl implements DGC {
}
/**
+ * Property name of the DGC serial filter to augment
+ * the built-in list of allowed types.
+ * Setting the property in the {@code lib/security/java.security} file
+ * will enable the augmented filter.
+ */
+ private static final String DGC_FILTER_PROPNAME = "sun.rmi.transport.dgcFilter";
+
+ /** Registry max depth of remote invocations. **/
+ private static int DGC_MAX_DEPTH = 5;
+
+ /** Registry maximum array size in remote invocations. **/
+ private static int DGC_MAX_ARRAY_SIZE = 10000;
+ /**
+ * The dgcFilter created from the value of the {@code "sun.rmi.transport.dgcFilter"}
+ * property.
+ */
+ private static final ObjectInputFilter dgcFilter =
+ AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)DGCImpl::initDgcFilter);
+
+ /**
+ * Initialize the dgcFilter from the security properties or system property; if any
+ * @return an ObjectInputFilter, or null
+ */
+ private static ObjectInputFilter initDgcFilter() {
+ ObjectInputFilter filter = null;
+ String props = System.getProperty(DGC_FILTER_PROPNAME);
+ if (props == null) {
+ props = Security.getProperty(DGC_FILTER_PROPNAME);
+ }
+ if (props != null) {
+ filter = ObjectInputFilter.Config.createFilter(props);
+ if (dgcLog.isLoggable(Log.BRIEF)) {
+ dgcLog.log(Log.BRIEF, "dgcFilter = " + filter);
+ }
+ }
+ return filter;
+ }
+
+ /**
* Construct a new server-side remote object collector at
* a particular port. Disallow construction from outside.
*/
@@ -295,7 +339,8 @@ final class DGCImpl implements DGC {
dgc = new DGCImpl();
ObjID dgcID = new ObjID(ObjID.DGC_ID);
LiveRef ref = new LiveRef(dgcID, 0);
- UnicastServerRef disp = new UnicastServerRef(ref);
+ UnicastServerRef disp = new UnicastServerRef(ref,
+ DGCImpl::checkInput);
Remote stub =
Util.createProxy(DGCImpl.class,
new UnicastRef(ref), true);
@@ -326,6 +371,53 @@ final class DGCImpl implements DGC {
});
}
+ /**
+ * ObjectInputFilter to filter DGC input objects.
+ * The list of acceptable classes is very short and explicit.
+ * The depth and array sizes are limited.
+ *
+ * @param filterInfo access to class, arrayLength, etc.
+ * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+ * {@link ObjectInputFilter.Status#REJECTED} if rejected,
+ * otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+ */
+ private static ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo filterInfo) {
+ if (dgcFilter != null) {
+ ObjectInputFilter.Status status = dgcFilter.checkInput(filterInfo);
+ if (status != ObjectInputFilter.Status.UNDECIDED) {
+ // The DGC filter can override the built-in white-list
+ return status;
+ }
+ }
+
+ if (filterInfo.depth() > DGC_MAX_DEPTH) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ Class<?> clazz = filterInfo.serialClass();
+ if (clazz != null) {
+ while (clazz.isArray()) {
+ if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > DGC_MAX_ARRAY_SIZE) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ // Arrays are allowed depending on the component type
+ clazz = clazz.getComponentType();
+ }
+ if (clazz.isPrimitive()) {
+ // Arrays of primitives are allowed
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ return (clazz == ObjID.class ||
+ clazz == UID.class ||
+ clazz == VMID.class ||
+ clazz == Lease.class)
+ ? ObjectInputFilter.Status.ALLOWED
+ : ObjectInputFilter.Status.REJECTED;
+ }
+ // Not a class, not size limited
+ return ObjectInputFilter.Status.UNDECIDED;
+ }
+
+
private static class LeaseInfo {
VMID vmid;
long expiration;
diff --git a/openjdk/jdk/src/share/classes/sun/security/ec/ECDSASignature.java b/openjdk/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
index e20120b..2abc262 100644
--- openjdk/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
+++ openjdk/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
package sun.security.ec;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.math.BigInteger;
@@ -363,13 +364,22 @@ abstract class ECDSASignature extends SignatureSpi {
}
// Convert the DER encoding of R and S into a concatenation of R and S
- private byte[] decodeSignature(byte[] signature) throws SignatureException {
+ private byte[] decodeSignature(byte[] sig) throws SignatureException {
try {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
BigInteger r = values[0].getPositiveBigInteger();
BigInteger s = values[1].getPositiveBigInteger();
+
// trim leading zeroes
byte[] rBytes = trimZeroes(r.toByteArray());
byte[] sBytes = trimZeroes(s.toByteArray());
@@ -383,7 +393,7 @@ abstract class ECDSASignature extends SignatureSpi {
return result;
} catch (Exception e) {
- throw new SignatureException("Could not decode signature", e);
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java b/openjdk/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
index d93a09f..78d3f63 100644
--- openjdk/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
@@ -498,6 +498,23 @@ public class SignerInfo implements DerEncoder {
return unauthenticatedAttributes;
}
+ /**
+ * Returns the timestamp PKCS7 data unverified.
+ * @return a PKCS7 object
+ */
+ public PKCS7 getTsToken() throws IOException {
+ if (unauthenticatedAttributes == null) {
+ return null;
+ }
+ PKCS9Attribute tsTokenAttr =
+ unauthenticatedAttributes.getAttribute(
+ PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
+ if (tsTokenAttr == null) {
+ return null;
+ }
+ return new PKCS7((byte[])tsTokenAttr.getValue());
+ }
+
/*
* Extracts a timestamp from a PKCS7 SignerInfo.
*
@@ -525,19 +542,12 @@ public class SignerInfo implements DerEncoder {
if (timestamp != null || !hasTimestamp)
return timestamp;
- if (unauthenticatedAttributes == null) {
- hasTimestamp = false;
- return null;
- }
- PKCS9Attribute tsTokenAttr =
- unauthenticatedAttributes.getAttribute(
- PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
- if (tsTokenAttr == null) {
+ PKCS7 tsToken = getTsToken();
+ if (tsToken == null) {
hasTimestamp = false;
return null;
}
- PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue());
// Extract the content (an encoded timestamp token info)
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
// Extract the signer (the Timestamping Authority)
diff --git a/openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java b/openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
index 1bac22c..0809ee4 100644
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -705,12 +705,21 @@ final class P11Signature extends SignatureSpi {
}
}
- private static byte[] asn1ToDSA(byte[] signature) throws SignatureException {
+ private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {
try {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
BigInteger r = values[0].getPositiveBigInteger();
BigInteger s = values[1].getPositiveBigInteger();
+
byte[] br = toByteArray(r, 20);
byte[] bs = toByteArray(s, 20);
if ((br == null) || (bs == null)) {
@@ -720,16 +729,25 @@ final class P11Signature extends SignatureSpi {
} catch (SignatureException e) {
throw e;
} catch (Exception e) {
- throw new SignatureException("invalid encoding for signature", e);
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
- private byte[] asn1ToECDSA(byte[] signature) throws SignatureException {
+ private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
try {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
+
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
+
BigInteger r = values[0].getPositiveBigInteger();
BigInteger s = values[1].getPositiveBigInteger();
+
// trim leading zeroes
byte[] br = KeyUtil.trimZeroes(r.toByteArray());
byte[] bs = KeyUtil.trimZeroes(s.toByteArray());
@@ -740,7 +758,7 @@ final class P11Signature extends SignatureSpi {
System.arraycopy(bs, 0, res, res.length - bs.length, bs.length);
return res;
} catch (Exception e) {
- throw new SignatureException("invalid encoding for signature", e);
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/provider/DSA.java b/openjdk/jdk/src/share/classes/sun/security/provider/DSA.java
index 071b5b0..3a13e91 100644
--- openjdk/jdk/src/share/classes/sun/security/provider/DSA.java
+++ openjdk/jdk/src/share/classes/sun/security/provider/DSA.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -267,14 +267,20 @@ abstract class DSA extends SignatureSpi {
BigInteger s = null;
// first decode the signature.
try {
- DerInputStream in = new DerInputStream(signature, offset, length);
+ // Enforce strict DER checking for signatures
+ DerInputStream in =
+ new DerInputStream(signature, offset, length, false);
DerValue[] values = in.getSequence(2);
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
r = values[0].getBigInteger();
s = values[1].getBigInteger();
-
} catch (IOException e) {
- throw new SignatureException("invalid encoding for signature");
+ throw new SignatureException("Invalid encoding for signature", e);
}
// some implementations do not correctly encode values in the ASN.1
@@ -366,13 +372,49 @@ abstract class DSA extends SignatureSpi {
return t5.mod(q);
}
- // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
protected BigInteger generateK(BigInteger q) {
+ // Implementation defined in FIPS 186-4 AppendixB.2.1.
SecureRandom random = getSigningRandom();
byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
random.nextBytes(kValue);
- return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+ BigInteger k = new BigInteger(1, kValue).mod(
+ q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+
+ // Using an equivalent exponent of fixed length (same as q or 1 bit
+ // less than q) to keep the kG timing relatively constant.
+ //
+ // Note that this is an extra step on top of the approach defined in
+ // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K.
+ k = k.add(q).divide(BigInteger.valueOf(2));
+
+ // An alternative implementation based on FIPS 186-4 AppendixB2.2
+ // with fixed-length K.
+ //
+ // Please keep it here as we may need to switch to it in the future.
+ //
+ // SecureRandom random = getSigningRandom();
+ // byte[] kValue = new byte[(q.bitLength() + 7)/8];
+ // BigInteger d = q.subtract(BigInteger.TWO);
+ // BigInteger k;
+ // do {
+ // random.nextBytes(kValue);
+ // BigInteger c = new BigInteger(1, kValue);
+ // if (c.compareTo(d) <= 0) {
+ // k = c.add(BigInteger.ONE);
+ // // Using an equivalent exponent of fixed length to keep
+ // // the g^k timing relatively constant.
+ // //
+ // // Note that this is an extra step on top of the approach
+ // // defined in FIPS 186-4 AppendixB.2.2 so as to make a
+ // // fixed length K.
+ // if (k.bitLength() >= q.bitLength()) {
+ // break;
+ // }
+ // }
+ // } while (true);
+
+ return k;
}
// Use the application-specified SecureRandom Object if provided.
diff --git a/openjdk/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/openjdk/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
index b826101..7303156 100644
--- openjdk/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
+++ openjdk/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.EnumSet;
-import java.util.HashSet;
import java.math.BigInteger;
import java.security.PublicKey;
import java.security.KeyFactory;
import java.security.AlgorithmParameters;
-import java.security.NoSuchAlgorithmException;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.X509CRL;
@@ -48,10 +46,13 @@ import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXReason;
-import java.io.IOException;
-import java.security.interfaces.*;
-import java.security.spec.*;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import sun.security.util.AnchorCertificates;
+import sun.security.util.CertConstraintParameters;
+import sun.security.util.Debug;
import sun.security.util.DisabledAlgorithmConstraints;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLImpl;
@@ -69,6 +70,7 @@ import sun.security.x509.AlgorithmId;
* @see PKIXParameters
*/
final public class AlgorithmChecker extends PKIXCertPathChecker {
+ private static final Debug debug = Debug.getInstance("certpath");
private final AlgorithmConstraints constraints;
private final PublicKey trustedPubKey;
@@ -88,6 +90,14 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
certPathDefaultConstraints = new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
+ // If there is no "cacerts" keyword, then disable anchor checking
+ private static final boolean publicCALimits =
+ certPathDefaultConstraints.checkProperty("jdkCA");
+
+ // If anchor checking enabled, this will be true if the trust anchor
+ // has a match in the cacerts file
+ private boolean trustedMatch = false;
+
/**
* Create a new <code>AlgorithmChecker</code> with the algorithm
* constraints specified in security property
@@ -136,6 +146,11 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+ // Check for anchor certificate restrictions
+ trustedMatch = checkFingerprint(anchor.getTrustedCert());
+ if (trustedMatch && debug != null) {
+ debug.println("trustedMatch = true");
+ }
} else {
this.trustedPubKey = anchor.getCAPublicKey();
}
@@ -144,6 +159,19 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
this.constraints = constraints;
}
+ // Check this 'cert' for restrictions in the AnchorCertificates
+ // trusted certificates list
+ private static boolean checkFingerprint(X509Certificate cert) {
+ if (!publicCALimits) {
+ return false;
+ }
+
+ if (debug != null) {
+ debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
+ }
+ return AnchorCertificates.contains(cert);
+ }
+
@Override
public void init(boolean forward) throws CertPathValidatorException {
// Note that this class does not support forward mode.
@@ -181,36 +209,8 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
return;
}
- X509CertImpl x509Cert = null;
- try {
- x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
- } catch (CertificateException ce) {
- throw new CertPathValidatorException(ce);
- }
-
- PublicKey currPubKey = x509Cert.getPublicKey();
- String currSigAlg = x509Cert.getSigAlgName();
-
- AlgorithmId algorithmId = null;
- try {
- algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
- } catch (CertificateException ce) {
- throw new CertPathValidatorException(ce);
- }
-
- AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
-
- // Check the current signature algorithm
- if (!constraints.permits(
- SIGNATURE_PRIMITIVE_SET,
- currSigAlg, currSigAlgParams)) {
- throw new CertPathValidatorException(
- "Algorithm constraints check failed: " + currSigAlg,
- null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
- }
-
// check the key usage and key size
- boolean[] keyUsage = x509Cert.getKeyUsage();
+ boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
if (keyUsage != null && keyUsage.length < 9) {
throw new CertPathValidatorException(
"incorrect KeyUsage extension",
@@ -248,28 +248,69 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
if (primitives.isEmpty()) {
throw new CertPathValidatorException(
- "incorrect KeyUsage extension",
+ "incorrect KeyUsage extension bits",
null, null, -1, PKIXReason.INVALID_KEY_USAGE);
}
}
+ PublicKey currPubKey = cert.getPublicKey();
+
+ if (constraints instanceof DisabledAlgorithmConstraints) {
+ // Check against DisabledAlgorithmConstraints certpath constraints.
+ // permits() will throw exception on failure.
+ ((DisabledAlgorithmConstraints)constraints).permits(primitives,
+ new CertConstraintParameters((X509Certificate)cert,
+ trustedMatch));
+ // If there is no previous key, set one and exit
+ if (prevPubKey == null) {
+ prevPubKey = currPubKey;
+ return;
+ }
+ }
+
+ X509CertImpl x509Cert;
+ AlgorithmId algorithmId;
+ try {
+ x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+ algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+ } catch (CertificateException ce) {
+ throw new CertPathValidatorException(ce);
+ }
+
+ AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+ String currSigAlg = x509Cert.getSigAlgName();
+
+ // If 'constraints' is not of DisabledAlgorithmConstraints, check all
+ // everything individually
+ if (!(constraints instanceof DisabledAlgorithmConstraints)) {
+ // Check the current signature algorithm
+ if (!constraints.permits(
+ SIGNATURE_PRIMITIVE_SET,
+ currSigAlg, currSigAlgParams)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on signature " +
+ "algorithm: " + currSigAlg, null, null, -1,
+ BasicReason.ALGORITHM_CONSTRAINED);
+ }
+
if (!constraints.permits(primitives, currPubKey)) {
throw new CertPathValidatorException(
- "algorithm constraints check failed",
+ "Algorithm constraints check failed on keysize: " +
+ sun.security.util.KeyUtil.getKeySize(currPubKey),
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
+ }
// Check with previous cert for signature algorithm and public key
if (prevPubKey != null) {
- if (currSigAlg != null) {
if (!constraints.permits(
SIGNATURE_PRIMITIVE_SET,
currSigAlg, prevPubKey, currSigAlgParams)) {
throw new CertPathValidatorException(
- "Algorithm constraints check failed: " + currSigAlg,
+ "Algorithm constraints check failed on " +
+ "signature algorithm: " + currSigAlg,
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
- }
// Inherit key parameters from previous key
if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) {
@@ -282,7 +323,7 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
if (params == null) {
throw new CertPathValidatorException(
- "Key parameters missing");
+ "Key parameters missing from public key.");
}
try {
@@ -330,6 +371,11 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
// Don't bother to change the trustedPubKey.
if (anchor.getTrustedCert() != null) {
prevPubKey = anchor.getTrustedCert().getPublicKey();
+ // Check for anchor certificate restrictions
+ trustedMatch = checkFingerprint(anchor.getTrustedCert());
+ if (trustedMatch && debug != null) {
+ debug.println("trustedMatch = true");
+ }
} else {
prevPubKey = anchor.getCAPublicKey();
}
@@ -370,7 +416,8 @@ final public class AlgorithmChecker extends PKIXCertPathChecker {
if (!certPathDefaultConstraints.permits(
SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
throw new CertPathValidatorException(
- "algorithm check failed: " + sigAlgName + " is disabled",
+ "Algorithm constraints check failed on signature algorithm: " +
+ sigAlgName + " is disabled",
null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java b/openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
index cfffba8..e85ef2d 100644
--- openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
+++ openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
@@ -131,8 +131,8 @@ class PKIXMasterCertPathValidator {
} catch (CertPathValidatorException cpve) {
throw new CertPathValidatorException(cpve.getMessage(),
- cpve.getCause(), cpOriginal, cpSize - (i + 1),
- cpve.getReason());
+ (cpve.getCause() != null) ? cpve.getCause() : cpve,
+ cpOriginal, cpSize - (i + 1), cpve.getReason());
}
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java b/openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java
new file mode 100644
index 0000000..34b4971
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package sun.security.provider.certpath;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Timestamp;
+import java.security.cert.CertSelector;
+import java.security.cert.CertStore;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.TrustAnchor;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class is a wrapper for PKIXBuilderParameters so that a Timestamp object
+ * can be passed alone when PKIXCertPath is checking signed jar files.
+ */
+
+public class PKIXTimestampParameters extends PKIXBuilderParameters {
+
+ private final PKIXBuilderParameters p;
+ private Timestamp jarTimestamp;
+
+ public PKIXTimestampParameters(PKIXBuilderParameters params,
+ Timestamp timestamp) throws InvalidAlgorithmParameterException {
+ super(params.getTrustAnchors(), null);
+ p = params;
+ jarTimestamp = timestamp;
+ }
+
+ public Timestamp getTimestamp() {
+ return jarTimestamp;
+ }
+ public void setTimestamp(Timestamp t) {
+ jarTimestamp = t;
+ }
+
+ @Override
+ public void setDate(Date d) {
+ p.setDate(d);
+ }
+
+ @Override
+ public void addCertPathChecker(PKIXCertPathChecker c) {
+ p.addCertPathChecker(c);
+ }
+
+ @Override
+ public void setMaxPathLength(int maxPathLength) {
+ p.setMaxPathLength(maxPathLength);
+ }
+
+ @Override
+ public int getMaxPathLength() {
+ return p.getMaxPathLength();
+ }
+
+ @Override
+ public String toString() {
+ return p.toString();
+ }
+
+ @Override
+ public Set<TrustAnchor> getTrustAnchors() {
+ return p.getTrustAnchors();
+ }
+
+ @Override
+ public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
+ throws InvalidAlgorithmParameterException {
+ // To avoid problems with PKIXBuilderParameter's constructors
+ if (p == null) {
+ return;
+ }
+ p.setTrustAnchors(trustAnchors);
+ }
+
+ @Override
+ public Set<String> getInitialPolicies() {
+ return p.getInitialPolicies();
+ }
+
+ @Override
+ public void setInitialPolicies(Set<String> initialPolicies) {
+ p.setInitialPolicies(initialPolicies);
+ }
+
+ @Override
+ public void setCertStores(List<CertStore> stores) {
+ p.setCertStores(stores);
+ }
+
+ @Override
+ public void addCertStore(CertStore store) {
+ p.addCertStore(store);
+ }
+
+ @Override
+ public List<CertStore> getCertStores() {
+ return p.getCertStores();
+ }
+
+ @Override
+ public void setRevocationEnabled(boolean val) {
+ p.setRevocationEnabled(val);
+ }
+
+ @Override
+ public boolean isRevocationEnabled() {
+ return p.isRevocationEnabled();
+ }
+
+ @Override
+ public void setExplicitPolicyRequired(boolean val) {
+ p.setExplicitPolicyRequired(val);
+ }
+
+ @Override
+ public boolean isExplicitPolicyRequired() {
+ return p.isExplicitPolicyRequired();
+ }
+
+ @Override
+ public void setPolicyMappingInhibited(boolean val) {
+ p.setPolicyMappingInhibited(val);
+ }
+
+ @Override
+ public boolean isPolicyMappingInhibited() {
+ return p.isPolicyMappingInhibited();
+ }
+
+ @Override
+ public void setAnyPolicyInhibited(boolean val) {
+ p.setAnyPolicyInhibited(val);
+ }
+
+ @Override
+ public boolean isAnyPolicyInhibited() {
+ return p.isAnyPolicyInhibited();
+ }
+
+ @Override
+ public void setPolicyQualifiersRejected(boolean qualifiersRejected) {
+ p.setPolicyQualifiersRejected(qualifiersRejected);
+ }
+
+ @Override
+ public boolean getPolicyQualifiersRejected() {
+ return p.getPolicyQualifiersRejected();
+ }
+
+ @Override
+ public Date getDate() {
+ return p.getDate();
+ }
+
+ @Override
+ public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) {
+ p.setCertPathCheckers(checkers);
+ }
+
+ @Override
+ public List<PKIXCertPathChecker> getCertPathCheckers() {
+ return p.getCertPathCheckers();
+ }
+
+ @Override
+ public String getSigProvider() {
+ return p.getSigProvider();
+ }
+
+ @Override
+ public void setSigProvider(String sigProvider) {
+ p.setSigProvider(sigProvider);
+ }
+
+ @Override
+ public CertSelector getTargetCertConstraints() {
+ return p.getTargetCertConstraints();
+ }
+
+ @Override
+ public void setTargetCertConstraints(CertSelector selector) {
+ // To avoid problems with PKIXBuilderParameter's constructors
+ if (p == null) {
+ return;
+ }
+ p.setTargetCertConstraints(selector);
+ }
+
+}
diff --git a/openjdk/jdk/src/share/classes/sun/security/rsa/RSASignature.java b/openjdk/jdk/src/share/classes/sun/security/rsa/RSASignature.java
index f1572f7..379d401 100644
--- openjdk/jdk/src/share/classes/sun/security/rsa/RSASignature.java
+++ openjdk/jdk/src/share/classes/sun/security/rsa/RSASignature.java
@@ -223,9 +223,10 @@ public abstract class RSASignature extends SignatureSpi {
* Decode the signature data. Verify that the object identifier matches
* and return the message digest.
*/
- public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature)
+ public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)
throws IOException {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
if ((values.length != 2) || (in.available() != 0)) {
throw new IOException("SEQUENCE length error");
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java b/openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
index 677a7e1..687eaee 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -326,36 +326,38 @@ final class CipherSuite implements Comparable<CipherSuite> {
static enum KeyExchange {
// key exchange algorithms
- K_NULL ("NULL", false),
- K_RSA ("RSA", true),
- K_RSA_EXPORT ("RSA_EXPORT", true),
- K_DH_RSA ("DH_RSA", false),
- K_DH_DSS ("DH_DSS", false),
- K_DHE_DSS ("DHE_DSS", true),
- K_DHE_RSA ("DHE_RSA", true),
- K_DH_ANON ("DH_anon", true),
-
- K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC),
- K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC),
- K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC),
- K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC),
- K_ECDH_ANON ("ECDH_anon", ALLOW_ECC),
+ K_NULL ("NULL", false, false),
+ K_RSA ("RSA", true, false),
+ K_RSA_EXPORT ("RSA_EXPORT", true, false),
+ K_DH_RSA ("DH_RSA", false, false),
+ K_DH_DSS ("DH_DSS", false, false),
+ K_DHE_DSS ("DHE_DSS", true, false),
+ K_DHE_RSA ("DHE_RSA", true, false),
+ K_DH_ANON ("DH_anon", true, false),
+
+ K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC, true),
+ K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC, true),
+ K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true),
+ K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC, true),
+ K_ECDH_ANON ("ECDH_anon", ALLOW_ECC, true),
// Kerberos cipher suites
- K_KRB5 ("KRB5", true),
- K_KRB5_EXPORT("KRB5_EXPORT", true),
+ K_KRB5 ("KRB5", true, false),
+ K_KRB5_EXPORT("KRB5_EXPORT", true, false),
// renegotiation protection request signaling cipher suite
- K_SCSV ("SCSV", true);
+ K_SCSV ("SCSV", true, false);
// name of the key exchange algorithm, e.g. DHE_DSS
final String name;
final boolean allowed;
+ final boolean isEC;
private final boolean alwaysAvailable;
- KeyExchange(String name, boolean allowed) {
+ KeyExchange(String name, boolean allowed, boolean isEC) {
this.name = name;
this.allowed = allowed;
+ this.isEC = isEC;
this.alwaysAvailable = allowed &&
(!name.startsWith("EC")) && (!name.startsWith("KRB"));
}
@@ -365,7 +367,7 @@ final class CipherSuite implements Comparable<CipherSuite> {
return true;
}
- if (name.startsWith("EC")) {
+ if (isEC) {
return (allowed && JsseJce.isEcAvailable());
} else if (name.startsWith("KRB")) {
return (allowed && JsseJce.isKerberosAvailable());
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java b/openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java
index 491bffa..a114f4a 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,20 +112,15 @@ final class CipherSuiteList {
boolean containsEC() {
if (containsEC == null) {
for (CipherSuite c : cipherSuites) {
- switch (c.keyExchange) {
- case K_ECDH_ECDSA:
- case K_ECDH_RSA:
- case K_ECDHE_ECDSA:
- case K_ECDHE_RSA:
- case K_ECDH_ANON:
+ if (c.keyExchange.isEC) {
containsEC = true;
return true;
- default:
- break;
}
}
+
containsEC = false;
}
+
return containsEC;
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/openjdk/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
index b16ff81..0d55552 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
@@ -621,8 +621,11 @@ final class ClientHandshaker extends Handshaker {
} else {
// we wanted to resume, but the server refused
//
- // Invalidate the session in case of reusing next time.
- session.invalidate();
+ // Invalidate the session for initial handshake in case
+ // of reusing next time.
+ if (isInitialHandshake) {
+ session.invalidate();
+ }
session = null;
if (!enableNewSession) {
throw new SSLException("New session creation is disabled");
@@ -762,30 +765,33 @@ final class ClientHandshaker extends Handshaker {
String typeName;
switch (certRequest.types[i]) {
- case CertificateRequest.cct_rsa_sign:
- typeName = "RSA";
- break;
+ case CertificateRequest.cct_rsa_sign:
+ typeName = "RSA";
+ break;
- case CertificateRequest.cct_dss_sign:
- typeName = "DSA";
- break;
+ case CertificateRequest.cct_dss_sign:
+ typeName = "DSA";
+ break;
- case CertificateRequest.cct_ecdsa_sign:
- // ignore if we do not have EC crypto available
- typeName = JsseJce.isEcAvailable() ? "EC" : null;
- break;
+ case CertificateRequest.cct_ecdsa_sign:
+ // ignore if we do not have EC crypto available
+ typeName = JsseJce.isEcAvailable() ? "EC" : null;
+ break;
- // Fixed DH/ECDH client authentication not supported
- case CertificateRequest.cct_rsa_fixed_dh:
- case CertificateRequest.cct_dss_fixed_dh:
- case CertificateRequest.cct_rsa_fixed_ecdh:
- case CertificateRequest.cct_ecdsa_fixed_ecdh:
- // Any other values (currently not used in TLS)
- case CertificateRequest.cct_rsa_ephemeral_dh:
- case CertificateRequest.cct_dss_ephemeral_dh:
- default:
- typeName = null;
- break;
+ // Fixed DH/ECDH client authentication not supported
+ //
+ // case CertificateRequest.cct_rsa_fixed_dh:
+ // case CertificateRequest.cct_dss_fixed_dh:
+ // case CertificateRequest.cct_rsa_fixed_ecdh:
+ // case CertificateRequest.cct_ecdsa_fixed_ecdh:
+ //
+ // Any other values (currently not used in TLS)
+ //
+ // case CertificateRequest.cct_rsa_ephemeral_dh:
+ // case CertificateRequest.cct_dss_ephemeral_dh:
+ default:
+ typeName = null;
+ break;
}
if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
@@ -813,18 +819,6 @@ final class ClientHandshaker extends Handshaker {
X509Certificate[] certs = km.getCertificateChain(alias);
if ((certs != null) && (certs.length != 0)) {
PublicKey publicKey = certs[0].getPublicKey();
- // for EC, make sure we use a supported named curve
- if (publicKey instanceof ECPublicKey) {
- ECParameterSpec params =
- ((ECPublicKey)publicKey).getParams();
- int index =
- SupportedEllipticCurvesExtension.getCurveIndex(
- params);
- if (!SupportedEllipticCurvesExtension.isSupported(
- index)) {
- publicKey = null;
- }
- }
if (publicKey != null) {
m1 = new CertificateMsg(certs);
signingKey = km.getPrivateKey(alias);
@@ -1385,6 +1379,17 @@ final class ClientHandshaker extends Handshaker {
sslContext.getSecureRandom(), maxProtocolVersion,
sessionId, cipherSuites);
+ // add elliptic curves and point format extensions
+ if (cipherSuites.containsEC()) {
+ SupportedEllipticCurvesExtension ece =
+ SupportedEllipticCurvesExtension.createExtension(algorithmConstraints);
+ if (ece != null) {
+ clientHelloMessage.extensions.add(ece);
+ clientHelloMessage.extensions.add(
+ SupportedEllipticPointFormatsExtension.DEFAULT);
+ }
+ }
+
// add signature_algorithm extension
if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
// we will always send the signature_algorithm extension
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java b/openjdk/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java
index b85c4c5..722c415 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,10 +56,11 @@ final class ECDHCrypt {
}
// Called by ServerHandshaker for ephemeral ECDH
- ECDHCrypt(String curveName, SecureRandom random) {
+ ECDHCrypt(int curveId, SecureRandom random) {
try {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
- ECGenParameterSpec params = new ECGenParameterSpec(curveName);
+ ECGenParameterSpec params =
+ SupportedEllipticCurvesExtension.getECGenParamSpec(curveId);
kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java b/openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
index 8ecaf78..a2312de 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
@@ -230,11 +230,6 @@ static final class ClientHello extends HandshakeMessage {
this.sessionId = sessionId;
this.cipherSuites = cipherSuites;
- if (cipherSuites.containsEC()) {
- extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
- extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
- }
-
clnt_random = new RandomCookie(generator);
compression_methods = NULL_COMPRESSION;
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java b/openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
index 7280d0d..38ecb29 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/Handshaker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -636,13 +636,41 @@ abstract class Handshaker {
ArrayList<CipherSuite> suites = new ArrayList<>();
if (!(activeProtocols.collection().isEmpty()) &&
activeProtocols.min.v != ProtocolVersion.NONE.v) {
+ boolean checkedCurves = false;
+ boolean hasCurves = false;
for (CipherSuite suite : enabledCipherSuites.collection()) {
if (suite.obsoleted > activeProtocols.min.v &&
suite.supported <= activeProtocols.max.v) {
if (algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
suite.name, null)) {
- suites.add(suite);
+ boolean available = true;
+ if (suite.keyExchange.isEC) {
+ if (!checkedCurves) {
+ hasCurves = SupportedEllipticCurvesExtension
+ .hasActiveCurves(algorithmConstraints);
+ checkedCurves = true;
+
+ if (!hasCurves && debug != null &&
+ Debug.isOn("verbose")) {
+ System.out.println(
+ "No available elliptic curves");
+ }
+ }
+
+ available = hasCurves;
+
+ if (!available && debug != null &&
+ Debug.isOn("verbose")) {
+ System.out.println(
+ "No active elliptic curves, ignore " +
+ suite);
+ }
+ }
+
+ if (available) {
+ suites.add(suite);
+ }
}
} else if (debug != null && Debug.isOn("verbose")) {
if (suite.obsoleted <= activeProtocols.min.v) {
@@ -679,18 +707,10 @@ abstract class Handshaker {
ProtocolList getActiveProtocols() {
if (activeProtocols == null) {
boolean enabledSSL20Hello = false;
+ boolean checkedCurves = false;
+ boolean hasCurves = false;
ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
for (ProtocolVersion protocol : enabledProtocols.collection()) {
- if (!algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- protocol.name, null)) {
- if (debug != null && Debug.isOn("verbose")) {
- System.out.println(
- "Ignoring disabled protocol: " + protocol);
- }
-
- continue;
- }
// Need not to check the SSL20Hello protocol.
if (protocol.v == ProtocolVersion.SSL20Hello.v) {
enabledSSL20Hello = true;
@@ -714,9 +734,36 @@ abstract class Handshaker {
if (algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
suite.name, null)) {
- protocols.add(protocol);
- found = true;
- break;
+
+ boolean available = true;
+ if (suite.keyExchange.isEC) {
+ if (!checkedCurves) {
+ hasCurves = SupportedEllipticCurvesExtension
+ .hasActiveCurves(algorithmConstraints);
+ checkedCurves = true;
+
+ if (!hasCurves && debug != null &&
+ Debug.isOn("verbose")) {
+ System.out.println(
+ "No activated elliptic curves");
+ }
+ }
+
+ available = hasCurves;
+
+ if (!available && debug != null &&
+ Debug.isOn("verbose")) {
+ System.out.println(
+ "No active elliptic curves, ignore " +
+ suite + " for " + protocol);
+ }
+ }
+
+ if (available) {
+ protocols.add(protocol);
+ found = true;
+ break;
+ }
} else if (debug != null && Debug.isOn("verbose")) {
System.out.println(
"Ignoring disabled cipher suite: " + suite +
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/JsseJce.java b/openjdk/jdk/src/share/classes/sun/security/ssl/JsseJce.java
index 923ae8e..d3262de 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/JsseJce.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/JsseJce.java
@@ -290,6 +290,15 @@ final class JsseJce {
}
}
+ static AlgorithmParameters getAlgorithmParameters(String algorithm)
+ throws NoSuchAlgorithmException {
+ if (cryptoProvider == null) {
+ return AlgorithmParameters.getInstance(algorithm);
+ } else {
+ return AlgorithmParameters.getInstance(algorithm, cryptoProvider);
+ }
+ }
+
static SecureRandom getSecureRandom() throws KeyManagementException {
if (cryptoProvider == null) {
return new SecureRandom();
@@ -409,6 +418,7 @@ final class JsseJce {
JsseJce.getKeyAgreement("ECDH");
JsseJce.getKeyFactory("EC");
JsseJce.getKeyPairGenerator("EC");
+ JsseJce.getAlgorithmParameters("EC");
} catch (Exception e) {
mediator = false;
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
index 373dc57..d983b60 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
@@ -92,7 +92,8 @@ final class ServerHandshaker extends Handshaker {
// we remember it for the RSA premaster secret version check
private ProtocolVersion clientRequestedVersion;
- private SupportedEllipticCurvesExtension supportedCurves;
+ // client supported elliptic curves
+ private SupportedEllipticCurvesExtension requestedCurves;
// the preferable signature algorithm used by ServerKeyExchange message
SignatureAndHashAlgorithm preferableSignatureAlgorithm;
@@ -682,7 +683,7 @@ final class ServerHandshaker extends Handshaker {
throw new SSLException("Client did not resume a session");
}
- supportedCurves = (SupportedEllipticCurvesExtension)
+ requestedCurves = (SupportedEllipticCurvesExtension)
mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
// We only need to handle the "signature_algorithm" extension
@@ -1025,11 +1026,18 @@ final class ServerHandshaker extends Handshaker {
if (trySetCipherSuite(suite) == false) {
continue;
}
+
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println("Standard ciphersuite chosen: " + suite);
+ }
return;
}
for (CipherSuite suite : legacySuites) {
if (trySetCipherSuite(suite)) {
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println("Legacy ciphersuite chosen: " + suite);
+ }
return;
}
}
@@ -1412,26 +1420,15 @@ final class ServerHandshaker extends Handshaker {
// If we cannot continue because we do not support any of the curves that
// the client requested, return false. Otherwise (all is well), return true.
private boolean setupEphemeralECDHKeys() {
- int index = -1;
- if (supportedCurves != null) {
- // if the client sent the supported curves extension, pick the
- // first one that we support;
- for (int curveId : supportedCurves.curveIds()) {
- if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
- index = curveId;
- break;
- }
- }
- if (index < 0) {
- // no match found, cannot use this ciphersuite
- return false;
- }
- } else {
- // pick our preference
- index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
+ int index = (requestedCurves != null) ?
+ requestedCurves.getPreferredCurve(algorithmConstraints) :
+ SupportedEllipticCurvesExtension.getActiveCurves(algorithmConstraints);
+ if (index < 0) {
+ // no match found, cannot use this ciphersuite
+ return false;
}
- String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
- ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
+
+ ecdh = new ECDHCrypt(index, sslContext.getSecureRandom());
return true;
}
@@ -1480,11 +1477,9 @@ final class ServerHandshaker extends Handshaker {
return false;
}
ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
- int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
- if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
- return false;
- }
- if ((supportedCurves != null) && !supportedCurves.contains(index)) {
+ int id = SupportedEllipticCurvesExtension.getCurveIndex(params);
+ if ((id <= 0) || !SupportedEllipticCurvesExtension.isSupported(id) ||
+ ((requestedCurves != null) && !requestedCurves.contains(id))) {
return false;
}
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java b/openjdk/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java
index 8933fab..b7757d6 100644
--- openjdk/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java
+++ openjdk/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java
@@ -27,39 +27,195 @@ package sun.security.ssl;
import java.io.IOException;
import java.security.spec.ECParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.AlgorithmParameters;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AccessController;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
-
+import java.util.ArrayList;
import javax.net.ssl.SSLProtocolException;
+import sun.security.action.GetPropertyAction;
+
final class SupportedEllipticCurvesExtension extends HelloExtension {
- // the extension value to send in the ClientHello message
- static final SupportedEllipticCurvesExtension DEFAULT;
+ private static final int ARBITRARY_PRIME = 0xff01;
+ private static final int ARBITRARY_CHAR2 = 0xff02;
+
+ // speed up the searching
+ private static final Map<String, Integer> oidToIdMap = new HashMap<>();
+ private static final Map<Integer, String> idToOidMap = new HashMap<>();
+
+ // speed up the parameters construction
+ private static final Map<Integer,
+ AlgorithmParameters> idToParams = new HashMap<>();
+
+ // the supported elliptic curves
+ private static final int[] supportedCurveIds;
+
+ // the curves of the extension
+ private final int[] curveIds;
+
+ // See sun.security.util.CurveDB for the OIDs
+ private static enum NamedEllipticCurve {
+ T163_K1(1, "sect163k1", "1.3.132.0.1", true), // NIST K-163
+ T163_R1(2, "sect163r1", "1.3.132.0.2", false),
+ T163_R2(3, "sect163r2", "1.3.132.0.15", true), // NIST B-163
+ T193_R1(4, "sect193r1", "1.3.132.0.24", false),
+ T193_R2(5, "sect193r2", "1.3.132.0.25", false),
+ T233_K1(6, "sect233k1", "1.3.132.0.26", true), // NIST K-233
+ T233_R1(7, "sect233r1", "1.3.132.0.27", true), // NIST B-233
+ T239_K1(8, "sect239k1", "1.3.132.0.3", false),
+ T283_K1(9, "sect283k1", "1.3.132.0.16", true), // NIST K-283
+ T283_R1(10, "sect283r1", "1.3.132.0.17", true), // NIST B-283
+ T409_K1(11, "sect409k1", "1.3.132.0.36", true), // NIST K-409
+ T409_R1(12, "sect409r1", "1.3.132.0.37", true), // NIST B-409
+ T571_K1(13, "sect571k1", "1.3.132.0.38", true), // NIST K-571
+ T571_R1(14, "sect571r1", "1.3.132.0.39", true), // NIST B-571
+
+ P160_K1(15, "secp160k1", "1.3.132.0.9", false),
+ P160_R1(16, "secp160r1", "1.3.132.0.8", false),
+ P160_R2(17, "secp160r2", "1.3.132.0.30", false),
+ P192_K1(18, "secp192k1", "1.3.132.0.31", false),
+ P192_R1(19, "secp192r1", "1.2.840.10045.3.1.1", true), // NIST P-192
+ P224_K1(20, "secp224k1", "1.3.132.0.32", false),
+ P224_R1(21, "secp224r1", "1.3.132.0.33", true), // NIST P-224
+ P256_K1(22, "secp256k1", "1.3.132.0.10", false),
+ P256_R1(23, "secp256r1", "1.2.840.10045.3.1.7", true), // NIST P-256
+ P384_R1(24, "secp384r1", "1.3.132.0.34", true), // NIST P-384
+ P521_R1(25, "secp521r1", "1.3.132.0.35", true); // NIST P-521
+
+ int id;
+ String name;
+ String oid;
+ boolean isFips;
+
+ NamedEllipticCurve(int id, String name, String oid, boolean isFips) {
+ this.id = id;
+ this.name = name;
+ this.oid = oid;
+ this.isFips = isFips;
- private static final boolean fips;
+ if (oidToIdMap.put(oid, id) != null ||
+ idToOidMap.put(id, oid) != null) {
+
+ throw new RuntimeException(
+ "Duplicate named elliptic curve definition: " + name);
+ }
+ }
+
+ static NamedEllipticCurve getCurve(String name, boolean requireFips) {
+ for (NamedEllipticCurve curve : NamedEllipticCurve.values()) {
+ if (curve.name.equals(name) && (!requireFips || curve.isFips)) {
+ return curve;
+ }
+ }
+
+ return null;
+ }
+ }
static {
- int[] ids;
- fips = SunJSSE.isFIPS();
- if (fips == false) {
- ids = new int[] {
- // NIST curves first
- // prefer NIST P-256, rest in order of increasing key length
- 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
- // non-NIST curves
- 15, 16, 17, 2, 18, 4, 5, 20, 8, 22,
- };
+ boolean requireFips = SunJSSE.isFIPS();
+
+ // hack code to initialize NamedEllipticCurve
+ NamedEllipticCurve nec =
+ NamedEllipticCurve.getCurve("secp256r1", false);
+
+ // The value of the System Property defines a list of enabled named
+ // curves in preference order, separated with comma. For example:
+ //
+ // jdk.tls.namedGroups="secp521r1, secp256r1, secp384r1"
+ //
+ // If the System Property is not defined or the value is empty, the
+ // default curves and preferences will be used.
+ String property = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.tls.namedGroups"));
+ if (property != null && property.length() != 0) {
+ // remove double quote marks from beginning/end of the property
+ if (property.length() > 1 && property.charAt(0) == '"' &&
+ property.charAt(property.length() - 1) == '"') {
+ property = property.substring(1, property.length() - 1);
+ }
+ }
+
+ ArrayList<Integer> idList;
+ if (property != null && property.length() != 0) { // customized curves
+ String[] curves = property.split(",");
+ idList = new ArrayList<>(curves.length);
+ for (String curve : curves) {
+ curve = curve.trim();
+ if (!curve.isEmpty()) {
+ NamedEllipticCurve namedCurve =
+ NamedEllipticCurve.getCurve(curve, requireFips);
+ if (namedCurve != null) {
+ if (isAvailableCurve(namedCurve.id)) {
+ idList.add(namedCurve.id);
+ }
+ } // ignore unknown curves
+ }
+ }
+ } else { // default curves
+ int[] ids;
+ if (requireFips) {
+ ids = new int[] {
+ // only NIST curves in FIPS mode
+ 23, 24, 25, 9, 10, 11, 12, 13, 14,
+ };
+ } else {
+ ids = new int[] {
+ // NIST curves first
+ 23, 24, 25, 9, 10, 11, 12, 13, 14,
+ // non-NIST curves
+ 22,
+ };
+ }
+
+ idList = new ArrayList<>(ids.length);
+ for (int curveId : ids) {
+ if (isAvailableCurve(curveId)) {
+ idList.add(curveId);
+ }
+ }
+ }
+
+ if (idList.isEmpty()) {
+ throw new IllegalArgumentException(
+ "System property jdk.tls.namedGroups(" + property + ") " +
+ "contains no supported elliptic curves");
} else {
- ids = new int[] {
- // same as above, but allow only NIST curves in FIPS mode
- 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
- };
+ supportedCurveIds = new int[idList.size()];
+ int i = 0;
+ for (Integer id : idList) {
+ supportedCurveIds[i++] = id;
+ }
}
- DEFAULT = new SupportedEllipticCurvesExtension(ids);
}
- private final int[] curveIds;
+ // check whether the curve is supported by the underlying providers
+ private static boolean isAvailableCurve(int curveId) {
+ String oid = idToOidMap.get(curveId);
+ if (oid != null) {
+ AlgorithmParameters params = null;
+ try {
+ params = JsseJce.getAlgorithmParameters("EC");
+ params.init(new ECGenParameterSpec(oid));
+ } catch (Exception e) {
+ return false;
+ }
+
+ // cache the parameters
+ idToParams.put(curveId, params);
+
+ return true;
+ }
+
+ return false;
+ }
private SupportedEllipticCurvesExtension(int[] curveIds) {
super(ExtensionType.EXT_ELLIPTIC_CURVES);
@@ -73,12 +229,67 @@ final class SupportedEllipticCurvesExtension extends HelloExtension {
if (((len & 1) != 0) || (k + 2 != len)) {
throw new SSLProtocolException("Invalid " + type + " extension");
}
+
+ // Note: unknown curves will be ignored later.
curveIds = new int[k >> 1];
for (int i = 0; i < curveIds.length; i++) {
curveIds[i] = s.getInt16();
}
}
+ // get the preferred active curve
+ static int getActiveCurves(AlgorithmConstraints constraints) {
+ return getPreferredCurve(supportedCurveIds, constraints);
+ }
+
+ static boolean hasActiveCurves(AlgorithmConstraints constraints) {
+ return getActiveCurves(constraints) >= 0;
+ }
+
+ static SupportedEllipticCurvesExtension createExtension(
+ AlgorithmConstraints constraints) {
+
+ ArrayList<Integer> idList = new ArrayList<>(supportedCurveIds.length);
+ for (int curveId : supportedCurveIds) {
+ if (constraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ "EC", idToParams.get(curveId))) {
+ idList.add(curveId);
+ }
+ }
+
+ if (!idList.isEmpty()) {
+ int[] ids = new int[idList.size()];
+ int i = 0;
+ for (Integer id : idList) {
+ ids[i++] = id;
+ }
+
+ return new SupportedEllipticCurvesExtension(ids);
+ }
+
+ return null;
+ }
+
+ // get the preferred activated curve
+ int getPreferredCurve(AlgorithmConstraints constraints) {
+ return getPreferredCurve(curveIds, constraints);
+ }
+
+ // get a preferred activated curve
+ private static int getPreferredCurve(int[] curves,
+ AlgorithmConstraints constraints) {
+ for (int curveId : curves) {
+ if (isSupported(curveId) && constraints.permits(
+ EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+ "EC", idToParams.get(curveId))) {
+ return curveId;
+ }
+ }
+
+ return -1;
+ }
+
boolean contains(int index) {
for (int curveId : curveIds) {
if (index == curveId) {
@@ -88,12 +299,6 @@ final class SupportedEllipticCurvesExtension extends HelloExtension {
return false;
}
- // Return a reference to the internal curveIds array.
- // The caller must NOT modify the contents.
- int[] curveIds() {
- return curveIds;
- }
-
@Override
int length() {
return 6 + (curveIds.length << 1);
@@ -121,18 +326,9 @@ final class SupportedEllipticCurvesExtension extends HelloExtension {
} else {
sb.append(", ");
}
- // first check if it is a known named curve, then try other cases.
- String oid = getCurveOid(curveId);
- if (oid != null) {
- ECParameterSpec spec = JsseJce.getECParameterSpec(oid);
- // this toString() output will look nice for the current
- // implementation of the ECParameterSpec class in the Sun
- // provider, but may not look good for other implementations.
- if (spec != null) {
- sb.append(spec.toString().split(" ")[0]);
- } else {
- sb.append(oid);
- }
+ String curveName = getCurveName(curveId);
+ if (curveName != null) {
+ sb.append(curveName);
} else if (curveId == ARBITRARY_PRIME) {
sb.append("arbitrary_explicit_prime_curves");
} else if (curveId == ARBITRARY_CHAR2) {
@@ -145,16 +341,15 @@ final class SupportedEllipticCurvesExtension extends HelloExtension {
return sb.toString();
}
- // Test whether we support the curve with the given index.
+ // Test whether the given curve is supported.
static boolean isSupported(int index) {
- if ((index <= 0) || (index >= NAMED_CURVE_OID_TABLE.length)) {
- return false;
- }
- if (fips == false) {
- // in non-FIPS mode, we support all valid indices
- return true;
+ for (int curveId : supportedCurveIds) {
+ if (index == curveId) {
+ return true;
+ }
}
- return DEFAULT.contains(index);
+
+ return false;
}
static int getCurveIndex(ECParameterSpec params) {
@@ -162,57 +357,32 @@ final class SupportedEllipticCurvesExtension extends HelloExtension {
if (oid == null) {
return -1;
}
- Integer n = curveIndices.get(oid);
+ Integer n = oidToIdMap.get(oid);
return (n == null) ? -1 : n;
}
static String getCurveOid(int index) {
- if ((index > 0) && (index < NAMED_CURVE_OID_TABLE.length)) {
- return NAMED_CURVE_OID_TABLE[index];
- }
- return null;
+ return idToOidMap.get(index);
}
- private final static int ARBITRARY_PRIME = 0xff01;
- private final static int ARBITRARY_CHAR2 = 0xff02;
-
- // See sun.security.ec.NamedCurve for the OIDs
- private final static String[] NAMED_CURVE_OID_TABLE = new String[] {
- null, // (0) unused
- "1.3.132.0.1", // (1) sect163k1, NIST K-163
- "1.3.132.0.2", // (2) sect163r1
- "1.3.132.0.15", // (3) sect163r2, NIST B-163
- "1.3.132.0.24", // (4) sect193r1
- "1.3.132.0.25", // (5) sect193r2
- "1.3.132.0.26", // (6) sect233k1, NIST K-233
- "1.3.132.0.27", // (7) sect233r1, NIST B-233
- "1.3.132.0.3", // (8) sect239k1
- "1.3.132.0.16", // (9) sect283k1, NIST K-283
- "1.3.132.0.17", // (10) sect283r1, NIST B-283
- "1.3.132.0.36", // (11) sect409k1, NIST K-409
- "1.3.132.0.37", // (12) sect409r1, NIST B-409
- "1.3.132.0.38", // (13) sect571k1, NIST K-571
- "1.3.132.0.39", // (14) sect571r1, NIST B-571
- "1.3.132.0.9", // (15) secp160k1
- "1.3.132.0.8", // (16) secp160r1
- "1.3.132.0.30", // (17) secp160r2
- "1.3.132.0.31", // (18) secp192k1
- "1.2.840.10045.3.1.1", // (19) secp192r1, NIST P-192
- "1.3.132.0.32", // (20) secp224k1
- "1.3.132.0.33", // (21) secp224r1, NIST P-224
- "1.3.132.0.10", // (22) secp256k1
- "1.2.840.10045.3.1.7", // (23) secp256r1, NIST P-256
- "1.3.132.0.34", // (24) secp384r1, NIST P-384
- "1.3.132.0.35", // (25) secp521r1, NIST P-521
- };
-
- private final static Map<String,Integer> curveIndices;
-
- static {
- curveIndices = new HashMap<String,Integer>();
- for (int i = 1; i < NAMED_CURVE_OID_TABLE.length; i++) {
- curveIndices.put(NAMED_CURVE_OID_TABLE[i], i);
+ static ECGenParameterSpec getECGenParamSpec(int index) {
+ AlgorithmParameters params = idToParams.get(index);
+ try {
+ return params.getParameterSpec(ECGenParameterSpec.class);
+ } catch (InvalidParameterSpecException ipse) {
+ // should be unlikely
+ String curveOid = getCurveOid(index);
+ return new ECGenParameterSpec(curveOid);
}
}
+ private static String getCurveName(int index) {
+ for (NamedEllipticCurve namedCurve : NamedEllipticCurve.values()) {
+ if (namedCurve.id == index) {
+ return namedCurve.name;
+ }
+ }
+
+ return null;
+ }
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java b/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
index 961921c..07962dc 100644
--- openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
+++ openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
@@ -53,6 +53,9 @@ import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.util.Map.Entry;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil;
import sun.security.tools.PathList;
import sun.security.x509.*;
@@ -97,6 +100,15 @@ public class Main {
private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
+ private static final DisabledAlgorithmConstraints DISABLED_CHECK =
+ new DisabledAlgorithmConstraints(
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+
+ private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
+ .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
+ private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
+ .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+
// Attention:
// This is the entry that get launched by the security tool jarsigner.
public static void main(String args[]) throws Exception {
@@ -172,6 +184,8 @@ public class Main {
private boolean badExtendedKeyUsage = false;
private boolean badNetscapeCertType = false;
+ private boolean seeWeak = false;
+
CertificateFactory certificateFactory;
CertPathValidator validator;
PKIXParameters pkixParameters;
@@ -577,6 +591,10 @@ public class Main {
{
boolean anySigned = false; // if there exists entry inside jar signed
JarFile jf = null;
+ Map<String,String> digestMap = new HashMap<>();
+ Map<String,PKCS7> sigMap = new HashMap<>();
+ Map<String,String> sigNameMap = new HashMap<>();
+ Map<String,String> unparsableSignatures = new HashMap<>();
try {
jf = new JarFile(jarName, true);
@@ -587,17 +605,44 @@ public class Main {
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
entriesVec.addElement(je);
- InputStream is = null;
+ try (InputStream is = jf.getInputStream(je)) {
+ String name = je.getName();
+ if (signatureRelated(name)
+ && SignatureFileVerifier.isBlockOrSF(name)) {
+ String alias = name.substring(name.lastIndexOf('/') + 1,
+ name.lastIndexOf('.'));
try {
- is = jf.getInputStream(je);
- int n;
- while ((n = is.read(buffer, 0, buffer.length)) != -1) {
+ if (name.endsWith(".SF")) {
+ Manifest sf = new Manifest(is);
+ boolean found = false;
+ for (Object obj : sf.getMainAttributes().keySet()) {
+ String key = obj.toString();
+ if (key.endsWith("-Digest-Manifest")) {
+ digestMap.put(alias,
+ key.substring(0, key.length() - 16));
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ unparsableSignatures.putIfAbsent(alias,
+ String.format(
+ rb.getString("history.unparsable"),
+ name));
+ }
+ } else {
+ sigNameMap.put(alias, name);
+ sigMap.put(alias, new PKCS7(is));
+ }
+ } catch (IOException ioe) {
+ unparsableSignatures.putIfAbsent(alias, String.format(
+ rb.getString("history.unparsable"), name));
+ }
+ } else {
+ while (is.read(buffer, 0, buffer.length) != -1) {
// we just read. this will throw a SecurityException
// if a signature/digest check fails.
}
- } finally {
- if (is != null) {
- is.close();
}
}
}
@@ -756,13 +801,106 @@ public class Main {
System.out.println(rb.getString(
".X.not.signed.by.specified.alias.es."));
}
- System.out.println();
}
- if (man == null)
+ if (man == null) {
+ System.out.println();
System.out.println(rb.getString("no.manifest."));
+ }
+
+ // Even if the verbose option is not specified, all out strings
+ // must be generated so seeWeak can be updated.
+ if (!digestMap.isEmpty()
+ || !sigMap.isEmpty()
+ || !unparsableSignatures.isEmpty()) {
+ if (verbose != null) {
+ System.out.println();
+ }
+ for (String s : sigMap.keySet()) {
+ if (!digestMap.containsKey(s)) {
+ unparsableSignatures.putIfAbsent(s, String.format(
+ rb.getString("history.nosf"), s));
+ }
+ }
+ for (String s : digestMap.keySet()) {
+ PKCS7 p7 = sigMap.get(s);
+ if (p7 != null) {
+ String history;
+ try {
+ SignerInfo si = p7.getSignerInfos()[0];
+ X509Certificate signer = si.getCertificate(p7);
+ String digestAlg = digestMap.get(s);
+ String sigAlg = AlgorithmId.makeSigAlg(
+ si.getDigestAlgorithmId().getName(),
+ si.getDigestEncryptionAlgorithmId().getName());
+ PublicKey key = signer.getPublicKey();
+ PKCS7 tsToken = si.getTsToken();
+ if (tsToken != null) {
+ SignerInfo tsSi = tsToken.getSignerInfos()[0];
+ X509Certificate tsSigner = tsSi.getCertificate(tsToken);
+ byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
+ TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
+ PublicKey tsKey = tsSigner.getPublicKey();
+ String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName();
+ String tsSigAlg = AlgorithmId.makeSigAlg(
+ tsSi.getDigestAlgorithmId().getName(),
+ tsSi.getDigestEncryptionAlgorithmId().getName());
+ Calendar c = Calendar.getInstance(
+ TimeZone.getTimeZone("UTC"),
+ Locale.getDefault(Locale.Category.FORMAT));
+ c.setTime(tsTokenInfo.getDate());
+ history = String.format(
+ rb.getString("history.with.ts"),
+ signer.getSubjectX500Principal(),
+ withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(sigAlg, SIG_PRIMITIVE_SET),
+ withWeak(key),
+ c,
+ tsSigner.getSubjectX500Principal(),
+ withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(tsSigAlg, SIG_PRIMITIVE_SET),
+ withWeak(tsKey));
+ } else {
+ history = String.format(
+ rb.getString("history.without.ts"),
+ signer.getSubjectX500Principal(),
+ withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(sigAlg, SIG_PRIMITIVE_SET),
+ withWeak(key));
+ }
+ } catch (Exception e) {
+ // The only usage of sigNameMap, remember the name
+ // of the block file if it's invalid.
+ history = String.format(
+ rb.getString("history.unparsable"),
+ sigNameMap.get(s));
+ }
+ if (verbose != null) {
+ System.out.println(history);
+ }
+ } else {
+ unparsableSignatures.putIfAbsent(s, String.format(
+ rb.getString("history.nobk"), s));
+ }
+ }
+ if (verbose != null) {
+ for (String s : unparsableSignatures.keySet()) {
+ System.out.println(unparsableSignatures.get(s));
+ }
+ }
+ }
+ System.out.println();
if (!anySigned) {
- if (hasSignature) {
+ if (seeWeak) {
+ if (verbose != null) {
+ System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose"));
+ System.out.println("\n " +
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS +
+ "=" + Security.getProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS));
+ } else {
+ System.out.println(rb.getString("jar.treated.unsigned.see.weak"));
+ }
+ } else if (hasSignature) {
System.out.println(rb.getString("jar.treated.unsigned"));
} else {
System.out.println(rb.getString("jar.is.unsigned"));
@@ -869,6 +1007,26 @@ public class Main {
System.exit(1);
}
+ private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
+ if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
+ return alg;
+ } else {
+ seeWeak = true;
+ return String.format(rb.getString("with.weak"), alg);
+ }
+ }
+
+ private String withWeak(PublicKey key) {
+ if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
+ return String.format(
+ rb.getString("key.bit"), KeyUtil.getKeySize(key));
+ } else {
+ seeWeak = true;
+ return String.format(
+ rb.getString("key.bit.weak"), KeyUtil.getKeySize(key));
+ }
+ }
+
private static MessageFormat validityTimeForm = null;
private static MessageFormat notYetTimeForm = null;
private static MessageFormat expiredTimeForm = null;
diff --git a/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java b/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
index 909d573..bff9dd7 100644
--- openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
+++ openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
@@ -138,11 +138,26 @@ public class Resources extends java.util.ListResourceBundle {
{"jar.is.unsigned",
"jar is unsigned."},
{"jar.treated.unsigned",
- "Signature not parsable or verifiable. The jar will be treated as unsigned. The jar may have been signed with a weak algorithm that is now disabled. For more information, rerun jarsigner with debug enabled (-J-Djava.security.debug=jar)."},
+ "WARNING: Signature is either not parsable or not verifiable, and the jar will be treated as unsigned. For more information, re-run jarsigner with debug enabled (-J-Djava.security.debug=jar)."},
+ {"jar.treated.unsigned.see.weak",
+ "The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled.\n\nRe-run jarsigner with the -verbose option for more details."},
+ {"jar.treated.unsigned.see.weak.verbose",
+ "WARNING: The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled by the security property:"},
{"jar.signed.", "jar signed."},
{"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
{"jar.verified.", "jar verified."},
{"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
+
+ {"history.with.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s\n Timestamped by \"%6$s\" on %5$tc\n Timestamp digest algorithm: %7$s\n Timestamp signature algorithm: %8$s, %9$s"},
+ {"history.without.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s"},
+ {"history.unparsable", "- Unparsable signature-related file %s"},
+ {"history.nosf", "- Missing signature-related file META-INF/%s.SF"},
+ {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"},
+
+ {"with.weak", "%s (weak)"},
+ {"key.bit", "%d-bit key"},
+ {"key.bit.weak", "%d-bit key (weak)"},
+
{"jarsigner.", "jarsigner: "},
{"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
"signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
diff --git a/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java b/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
index b471210..86b74b9 100644
--- openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
+++ openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
@@ -135,12 +135,29 @@ public class Resources_ja extends java.util.ListResourceBundle {
{"no.manifest.", "\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"},
{".Signature.related.entries.","(\u30B7\u30B0\u30CD\u30C1\u30E3\u95A2\u9023\u30A8\u30F3\u30C8\u30EA)"},
{".Unsigned.entries.", "(\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA)"},
- {"jar.is.unsigned.signatures.missing.or.not.parsable.",
- "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002(\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u304B\u3001\u69CB\u6587\u89E3\u6790\u3067\u304D\u307E\u305B\u3093)"},
+ {"jar.is.unsigned",
+ "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
+ {"jar.treated.unsigned",
+ "\u8B66\u544A: \u7F72\u540D\u304C\u69CB\u6587\u89E3\u6790\u3067\u304D\u306A\u3044\u304B\u691C\u8A3C\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3053\u306Ejar\u306F\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001\u30C7\u30D0\u30C3\u30B0\u3092\u6709\u52B9\u306B\u3057\u3066(-J-Djava.security.debug=jar) jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
+ {"jar.treated.unsigned.see.weak",
+ "\u3053\u306Ejar\u306F\u3001\u73FE\u5728\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u308B\u5F31\u3044\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002\n\n\u8A73\u7D30\u306F\u3001-verbose\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
+ {"jar.treated.unsigned.see.weak.verbose",
+ "\u8B66\u544A: \u3053\u306Ejar\u306F\u3001\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u3088\u3063\u3066\u73FE\u5728\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u308B\u5F31\u3044\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059:"},
{"jar.signed.", "jar\u306F\u7F72\u540D\u3055\u308C\u307E\u3057\u305F\u3002"},
{"jar.signed.with.signer.errors.", "jar\u306F\u7F72\u540D\u3055\u308C\u307E\u3057\u305F - \u7F72\u540D\u8005\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002"},
{"jar.verified.", "jar\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F\u3002"},
{"jar.verified.with.signer.errors.", "jar\u306F\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F - \u7F72\u540D\u8005\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002"},
+
+ {"history.with.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u4ED8\u52A0\u8005: \"%6$s\" \u65E5\u6642: %5$tc\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %7$s\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %8$s\u3001%9$s"},
+ {"history.without.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s"},
+ {"history.unparsable", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EB%s\u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093"},
+ {"history.nosf", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u304C\u3042\u308A\u307E\u305B\u3093"},
+ {"history.nobk", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u306E\u30D6\u30ED\u30C3\u30AF\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093"},
+
+ {"with.weak", "%s (\u5F31)"},
+ {"key.bit", "%d\u30D3\u30C3\u30C8\u9375"},
+ {"key.bit.weak", "%d\u30D3\u30C3\u30C8\u9375(\u5F31)"},
+
{"jarsigner.", "jarsigner: "},
{"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
"\u30B7\u30B0\u30CD\u30C1\u30E3\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u306B\u4F7F\u7528\u3067\u304D\u308B\u6587\u5B57\u306F\u3001A-Z\u30010-9\u3001_\u3001- \u306E\u307F\u3067\u3059\u3002"},
diff --git a/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java b/openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
index 76f88c1..e99405b 100644
--- openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
+++ openjdk/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
@@ -135,12 +135,29 @@ public class Resources_zh_CN extends java.util.ListResourceBundle {
{"no.manifest.", "\u6CA1\u6709\u6E05\u5355\u3002"},
{".Signature.related.entries.","(\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6761\u76EE)"},
{".Unsigned.entries.", "(\u672A\u7B7E\u540D\u6761\u76EE)"},
- {"jar.is.unsigned.signatures.missing.or.not.parsable.",
- "jar \u672A\u7B7E\u540D\u3002(\u7F3A\u5C11\u7B7E\u540D\u6216\u65E0\u6CD5\u89E3\u6790\u7B7E\u540D)"},
+ {"jar.is.unsigned",
+ "jar \u672A\u7B7E\u540D\u3002"},
+ {"jar.treated.unsigned",
+ "\u8B66\u544A: \u7B7E\u540D\u65E0\u6CD5\u89E3\u6790\u6216\u9A8C\u8BC1, \u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D\u3002\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u5728\u542F\u7528\u8C03\u8BD5\u7684\u60C5\u51B5\u4E0B\u91CD\u65B0\u8FD0\u884C jarsigner (-J-Djava.security.debug=jar)\u3002"},
+ {"jar.treated.unsigned.see.weak",
+ "\u7531\u4E8E\u8BE5 jar \u662F\u4F7F\u7528\u76EE\u524D\u5DF2\u7981\u7528\u7684\u5F31\u7B97\u6CD5\u7B7E\u540D\u7684, \u56E0\u6B64\u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D\u3002\n\n\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u9009\u9879\u91CD\u65B0\u8FD0\u884C jarsigner\u3002"},
+ {"jar.treated.unsigned.see.weak.verbose",
+ "\u8B66\u544A: \u7531\u4E8E\u8BE5 jar \u662F\u4F7F\u7528\u76EE\u524D\u5DF2\u7531\u5B89\u5168\u5C5E\u6027\u7981\u7528\u7684\u5F31\u7B97\u6CD5\u7B7E\u540D\u7684, \u56E0\u6B64\u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D:"},
{"jar.signed.", "jar \u5DF2\u7B7E\u540D\u3002"},
{"jar.signed.with.signer.errors.", "jar \u5DF2\u7B7E\u540D, \u4F46\u51FA\u73B0\u7B7E\u540D\u8005\u9519\u8BEF\u3002"},
{"jar.verified.", "jar \u5DF2\u9A8C\u8BC1\u3002"},
{"jar.verified.with.signer.errors.", "jar \u5DF2\u9A8C\u8BC1, \u4F46\u51FA\u73B0\u7B7E\u540D\u8005\u9519\u8BEF\u3002"},
+
+ {"history.with.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n \u6458\u8981\u7B97\u6CD5: %2$s\n \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s\n \u7531 \"%6$s\" \u4E8E %5$tc \u52A0\u65F6\u95F4\u6233\n \u65F6\u95F4\u6233\u6458\u8981\u7B97\u6CD5: %7$s\n \u65F6\u95F4\u6233\u7B7E\u540D\u7B97\u6CD5: %8$s, %9$s"},
+ {"history.without.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n \u6458\u8981\u7B97\u6CD5: %2$s\n \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s"},
+ {"history.unparsable", "- \u65E0\u6CD5\u89E3\u6790\u7684\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 %s"},
+ {"history.nosf", "- \u7F3A\u5C11\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF"},
+ {"history.nobk", "- \u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF \u7F3A\u5C11\u5757\u6587\u4EF6"},
+
+ {"with.weak", "%s (\u5F31)"},
+ {"key.bit", "%d \u4F4D\u5BC6\u94A5"},
+ {"key.bit.weak", "%d \u4F4D\u5BC6\u94A5 (\u5F31)"},
+
{"jarsigner.", "jarsigner: "},
{"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
"\u7B7E\u540D\u6587\u4EF6\u540D\u5FC5\u987B\u5305\u542B\u4EE5\u4E0B\u5B57\u7B26: A-Z, 0-9, _ \u6216 -"},
diff --git a/openjdk/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java b/openjdk/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java
index 4199ff4..f9eee0b 100644
--- openjdk/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java
+++ openjdk/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@ public class Resources_sv extends java.util.ListResourceBundle {
{"Illegal.option.option", "Otill\u00E5tet alternativ: {0}"},
{"Usage.policytool.options.", "Syntax: policytool [alternativ]"},
{".file.file.policy.file.location",
- " [-file <fil>] policyfilens plats"},
+ " [-file <fil>] policyfiladress"},
{"New", "&Nytt"},
{"Open", "&\u00D6ppna..."},
{"Save", "S¶"},
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java b/openjdk/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
index 6175fea..e7ed756 100644
--- openjdk/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
+++ openjdk/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@ import java.security.AccessController;
import java.security.AlgorithmConstraints;
import java.security.PrivilegedAction;
import java.security.Security;
-import java.util.Map;
import java.util.Set;
/**
@@ -45,8 +44,7 @@ public abstract class AbstractAlgorithmConstraints
}
// Get algorithm constraints from the specified security property.
- private static void loadAlgorithmsMap(Map<String, String[]> algorithmsMap,
- String propertyName) {
+ static String[] getAlgorithms(String propertyName) {
String property = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
@@ -72,18 +70,7 @@ public abstract class AbstractAlgorithmConstraints
if (algorithmsInProperty == null) {
algorithmsInProperty = new String[0];
}
- algorithmsMap.put(propertyName, algorithmsInProperty);
- }
-
- static String[] getAlgorithms(Map<String, String[]> algorithmsMap,
- String propertyName) {
- synchronized (algorithmsMap) {
- if (!algorithmsMap.containsKey(propertyName)) {
- loadAlgorithmsMap(algorithmsMap, propertyName);
- }
-
- return algorithmsMap.get(propertyName);
- }
+ return algorithmsInProperty;
}
static boolean checkAlgorithm(String[] algorithms, String algorithm,
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java b/openjdk/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
index 394b846..dae529a 100644
--- openjdk/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
+++ openjdk/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,19 +38,7 @@ public class AlgorithmDecomposer {
private static final Pattern pattern =
Pattern.compile("with|and", Pattern.CASE_INSENSITIVE);
- /**
- * Decompose the standard algorithm name into sub-elements.
- * <p>
- * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
- * so that we can check the "SHA1" and "RSA" algorithm constraints
- * separately.
- * <p>
- * Please override the method if need to support more name pattern.
- */
- public Set<String> decompose(String algorithm) {
- if (algorithm == null || algorithm.length() == 0) {
- return new HashSet<>();
- }
+ private static Set<String> decomposeImpl(String algorithm) {
// algorithm/mode/padding
String[] transTockens = transPattern.split(algorithm);
@@ -76,6 +64,24 @@ public class AlgorithmDecomposer {
elements.add(token);
}
}
+ return elements;
+ }
+
+ /**
+ * Decompose the standard algorithm name into sub-elements.
+ * <p>
+ * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+ * so that we can check the "SHA1" and "RSA" algorithm constraints
+ * separately.
+ * <p>
+ * Please override the method if need to support more name pattern.
+ */
+ public Set<String> decompose(String algorithm) {
+ if (algorithm == null || algorithm.length() == 0) {
+ return new HashSet<>();
+ }
+
+ Set<String> elements = decomposeImpl(algorithm);
// In Java standard algorithm name specification, for different
// purpose, the SHA-1 and SHA-2 algorithm names are different. For
@@ -127,4 +133,40 @@ public class AlgorithmDecomposer {
return elements;
}
+ private static void hasLoop(Set<String> elements, String find, String replace) {
+ if (elements.contains(find)) {
+ if (!elements.contains(replace)) {
+ elements.add(replace);
+}
+ elements.remove(find);
+ }
+ }
+
+ /*
+ * This decomposes a standard name into sub-elements with a consistent
+ * message digest algorithm name to avoid overly complicated checking.
+ */
+ public static Set<String> decomposeOneHash(String algorithm) {
+ if (algorithm == null || algorithm.length() == 0) {
+ return new HashSet<>();
+ }
+
+ Set<String> elements = decomposeImpl(algorithm);
+
+ hasLoop(elements, "SHA-1", "SHA1");
+ hasLoop(elements, "SHA-224", "SHA224");
+ hasLoop(elements, "SHA-256", "SHA256");
+ hasLoop(elements, "SHA-384", "SHA384");
+ hasLoop(elements, "SHA-512", "SHA512");
+
+ return elements;
+ }
+
+ /*
+ * The provided message digest algorithm name will return a consistent
+ * naming scheme.
+ */
+ public static String hashName(String algorithm) {
+ return algorithm.replace("-", "");
+ }
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/AnchorCertificates.java b/openjdk/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
new file mode 100644
index 0000000..8498342
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.AccessController;
+import java.security.KeyStore;
+import java.security.PrivilegedAction;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashSet;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * The purpose of this class is to determine the trust anchor certificates is in
+ * the cacerts file. This is used for PKIX CertPath checking.
+ */
+public class AnchorCertificates {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+ private static final String HASH = "SHA-256";
+ private static HashSet<String> certs;
+
+ static {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ File f = new File(System.getProperty("java.home"),
+ "lib/security/cacerts");
+ KeyStore cacerts;
+ try {
+ cacerts = KeyStore.getInstance("JKS");
+ try (FileInputStream fis = new FileInputStream(f)) {
+ cacerts.load(fis, null);
+ certs = new HashSet<>();
+ Enumeration<String> list = cacerts.aliases();
+ String alias;
+ while (list.hasMoreElements()) {
+ alias = list.nextElement();
+ // Check if this cert is labeled a trust anchor.
+ if (alias.contains(" [jdk")) {
+ X509Certificate cert = (X509Certificate) cacerts
+ .getCertificate(alias);
+ certs.add(X509CertImpl.getFingerprint(HASH, cert));
+ }
+ }
+ }
+ } catch (Exception e) {
+ if (debug != null) {
+ debug.println("Error parsing cacerts");
+ }
+ e.printStackTrace();
+ }
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Checks if a certificate is a trust anchor.
+ *
+ * @param cert the certificate to check
+ * @return true if the certificate is trusted.
+ */
+ public static boolean contains(X509Certificate cert) {
+ String key = X509CertImpl.getFingerprint(HASH, cert);
+ boolean result = certs.contains(key);
+ if (result && debug != null) {
+ debug.println("AnchorCertificate.contains: matched " +
+ cert.getSubjectDN());
+ }
+ return result;
+ }
+
+ private AnchorCertificates() {}
+}
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/CertConstraintParameters.java b/openjdk/jdk/src/share/classes/sun/security/util/CertConstraintParameters.java
new file mode 100644
index 0000000..9f7a938
--- /dev/null
+++ openjdk/jdk/src/share/classes/sun/security/util/CertConstraintParameters.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This class is a wrapper for keeping state and passing objects between PKIX,
+ * AlgorithmChecker, and DisabledAlgorithmConstraints.
+ */
+public class CertConstraintParameters {
+ // A certificate being passed to check against constraints.
+ private final X509Certificate cert;
+
+ // This is true if the trust anchor in the certificate chain matches a cert
+ // in AnchorCertificates
+ private final boolean trustedMatch;
+
+ public CertConstraintParameters(X509Certificate c, boolean match) {
+ cert = c;
+ trustedMatch = match;
+ }
+
+ public CertConstraintParameters(X509Certificate c) {
+ this(c, false);
+ }
+
+ // Returns if the trust anchor has a match if anchor checking is enabled.
+ public boolean isTrustedMatch() {
+ return trustedMatch;
+ }
+
+ public X509Certificate getCertificate() {
+ return cert;
+ }
+}
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/DerInputBuffer.java b/openjdk/jdk/src/share/classes/sun/security/util/DerInputBuffer.java
index 786e791..7d3ad55 100644
--- openjdk/jdk/src/share/classes/sun/security/util/DerInputBuffer.java
+++ openjdk/jdk/src/share/classes/sun/security/util/DerInputBuffer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -147,6 +147,11 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
System.arraycopy(buf, pos, bytes, 0, len);
skip(len);
+ // check to make sure no extra leading 0s for DER
+ if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) {
+ throw new IOException("Invalid encoding: redundant leading 0s");
+ }
+
if (makePositive) {
return new BigInteger(1, bytes);
} else {
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/DerInputStream.java b/openjdk/jdk/src/share/classes/sun/security/util/DerInputStream.java
index fc4aee8..5af3cf4 100644
--- openjdk/jdk/src/share/classes/sun/security/util/DerInputStream.java
+++ openjdk/jdk/src/share/classes/sun/security/util/DerInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@ public class DerInputStream {
* @param data the buffer from which to create the string (CONSUMED)
*/
public DerInputStream(byte[] data) throws IOException {
- init(data, 0, data.length);
+ init(data, 0, data.length, true);
}
/**
@@ -92,23 +92,48 @@ public class DerInputStream {
* starting at "offset"
*/
public DerInputStream(byte[] data, int offset, int len) throws IOException {
- init(data, offset, len);
+ init(data, offset, len, true);
+ }
+
+ /**
+ * Create a DER input stream from part of a data buffer with
+ * additional arg to indicate whether to allow constructed
+ * indefinite-length encoding.
+ * The buffer is not copied, it is shared. Accordingly, the
+ * buffer should be treated as read-only.
+ *
+ * @param data the buffer from which to create the string (CONSUMED)
+ * @param offset the first index of <em>data</em> which will
+ * be read as DER input in the new stream
+ * @param len how long a chunk of the buffer to use,
+ * starting at "offset"
+ * @param allowIndefiniteLength whether to allow constructed
+ * indefinite-length encoding
+ */
+ public DerInputStream(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
+ init(data, offset, len, allowIndefiniteLength);
}
/*
* private helper routine
*/
- private void init(byte[] data, int offset, int len) throws IOException {
+ private void init(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
if ((offset+2 > data.length) || (offset+len > data.length)) {
throw new IOException("Encoding bytes too short");
}
// check for indefinite length encoding
if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
- byte[] inData = new byte[len];
- System.arraycopy(data, offset, inData, 0, len);
-
- DerIndefLenConverter derIn = new DerIndefLenConverter();
- buffer = new DerInputBuffer(derIn.convert(inData));
+ if (!allowIndefiniteLength) {
+ throw new IOException("Indefinite length BER encoding found");
+ } else {
+ byte[] inData = new byte[len];
+ System.arraycopy(data, offset, inData, 0, len);
+
+ DerIndefLenConverter derIn = new DerIndefLenConverter();
+ buffer = new DerInputBuffer(derIn.convert(inData));
+ }
} else
buffer = new DerInputBuffer(data, offset, len);
buffer.mark(Integer.MAX_VALUE);
@@ -233,12 +258,21 @@ public class DerInputStream {
* First byte = number of excess bits in the last octet of the
* representation.
*/
- int validBits = length*8 - buffer.read();
+ int excessBits = buffer.read();
+ if (excessBits < 0) {
+ throw new IOException("Unused bits of bit string invalid");
+ }
+ int validBits = length*8 - excessBits;
+ if (validBits < 0) {
+ throw new IOException("Valid bits of bit string invalid");
+ }
byte[] repn = new byte[length];
- if ((length != 0) && (buffer.read(repn) != length))
- throw new IOException("short read of DER bit string");
+ if ((length != 0) && (buffer.read(repn) != length)) {
+ throw new IOException("Short read of DER bit string");
+ }
+
return new BitArray(validBits, repn);
}
@@ -252,7 +286,7 @@ public class DerInputStream {
int length = getLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
return retval;
}
@@ -262,7 +296,7 @@ public class DerInputStream {
*/
public void getBytes(byte[] val) throws IOException {
if ((val.length != 0) && (buffer.read(val) != val.length)) {
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
}
}
@@ -346,7 +380,7 @@ public class DerInputStream {
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
- int len = getLength((lenByte & 0xff), buffer);
+ int len = getLength(lenByte, buffer);
if (len == -1) {
// indefinite length encoding found
@@ -392,7 +426,7 @@ public class DerInputStream {
} while (newstr.available() > 0);
if (newstr.available() != 0)
- throw new IOException("extra data at end of vector");
+ throw new IOException("Extra data at end of vector");
/*
* Now stick them into the array we're returning.
@@ -483,7 +517,7 @@ public class DerInputStream {
int length = getLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER " +
+ throw new IOException("Short read of DER " +
stringName + " string");
return new String(retval, enc);
@@ -544,7 +578,11 @@ public class DerInputStream {
*/
static int getLength(int lenByte, InputStream in) throws IOException {
int value, tmp;
+ if (lenByte == -1) {
+ throw new IOException("Short read of DER length");
+ }
+ String mdName = "DerInputStream.getLength(): ";
tmp = lenByte;
if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
value = tmp;
@@ -558,17 +596,23 @@ public class DerInputStream {
if (tmp == 0)
return -1;
if (tmp < 0 || tmp > 4)
- throw new IOException("DerInputStream.getLength(): lengthTag="
- + tmp + ", "
+ throw new IOException(mdName + "lengthTag=" + tmp + ", "
+ ((tmp < 0) ? "incorrect DER encoding." : "too big."));
- for (value = 0; tmp > 0; tmp --) {
+ value = 0x0ff & in.read();
+ tmp--;
+ if (value == 0) {
+ // DER requires length value be encoded in minimum number of bytes
+ throw new IOException(mdName + "Redundant length bytes found");
+ }
+ while (tmp-- > 0) {
value <<= 8;
value += 0x0ff & in.read();
}
if (value < 0) {
- throw new IOException("DerInputStream.getLength(): "
- + "Invalid length bytes");
+ throw new IOException(mdName + "Invalid length bytes");
+ } else if (value <= 127) {
+ throw new IOException(mdName + "Should use short form for length");
}
}
return value;
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/DerValue.java b/openjdk/jdk/src/share/classes/sun/security/util/DerValue.java
index beb51c1..8cd989b 100644
--- openjdk/jdk/src/share/classes/sun/security/util/DerValue.java
+++ openjdk/jdk/src/share/classes/sun/security/util/DerValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -249,7 +249,7 @@ public class DerValue {
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
DerInputBuffer inbuf = in.dup();
int readLen = inbuf.available();
@@ -362,7 +362,7 @@ public class DerValue {
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
int readLen = in.available();
int offset = 2; // for tag and length bytes
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/openjdk/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
index a102187..af1f99b 100644
--- openjdk/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
+++ openjdk/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,14 @@ package sun.security.util;
import java.security.CryptoPrimitive;
import java.security.AlgorithmParameters;
import java.security.Key;
-import java.util.Locale;
-import java.util.Set;
-import java.util.Collections;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertPathValidatorException.BasicReason;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Map;
-import java.util.HashMap;
+import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -44,6 +46,7 @@ import java.util.regex.Matcher;
* for the syntax of the disabled algorithm string.
*/
public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
+ private static final Debug debug = Debug.getInstance("certpath");
// the known security property, jdk.certpath.disabledAlgorithms
public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
@@ -53,17 +56,12 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
public final static String PROPERTY_TLS_DISABLED_ALGS =
"jdk.tls.disabledAlgorithms";
- private final static Map<String, String[]> disabledAlgorithmsMap =
- new HashMap<>();
- private final static Map<String, KeySizeConstraints> keySizeConstraintsMap =
- new HashMap<>();
-
// the known security property, jdk.jar.disabledAlgorithms
public static final String PROPERTY_JAR_DISABLED_ALGS =
"jdk.jar.disabledAlgorithms";
private final String[] disabledAlgorithms;
- private final KeySizeConstraints keySizeConstraints;
+ private final Constraints algorithmConstraints;
/**
* Initialize algorithm constraints with the specified security property.
@@ -86,11 +84,14 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
public DisabledAlgorithmConstraints(String propertyName,
AlgorithmDecomposer decomposer) {
super(decomposer);
- disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName);
- keySizeConstraints = getKeySizeConstraints(disabledAlgorithms,
- propertyName);
+ disabledAlgorithms = getAlgorithms(propertyName);
+ algorithmConstraints = new Constraints(disabledAlgorithms);
}
+ /*
+ * This only checks if the algorithm has been completely disabled. If
+ * there are keysize or other limit, this method allow the algorithm.
+ */
@Override
final public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) {
@@ -103,11 +104,19 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
}
+ /*
+ * Checks if the key algorithm has been disabled or constraints have been
+ * placed on the key.
+ */
@Override
final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
return checkConstraints(primitives, "", key, null);
}
+ /*
+ * Checks if the key algorithm has been disabled or if constraints have
+ * been placed on the key.
+ */
@Override
final public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) {
@@ -119,7 +128,39 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return checkConstraints(primitives, algorithm, key, parameters);
}
- // Check algorithm constraints
+ /*
+ * Check if a x509Certificate object is permitted. Check if all
+ * algorithms are allowed, certificate constraints, and the
+ * public key against key constraints.
+ *
+ * Uses new style permit() which throws exceptions.
+ */
+ public final void permits(Set<CryptoPrimitive> primitives,
+ CertConstraintParameters cp) throws CertPathValidatorException {
+ checkConstraints(primitives, cp);
+ }
+
+ /*
+ * Check if Certificate object is within the constraints.
+ * Uses new style permit() which throws exceptions.
+ */
+ public final void permits(Set<CryptoPrimitive> primitives,
+ X509Certificate cert) throws CertPathValidatorException {
+ checkConstraints(primitives, new CertConstraintParameters(cert));
+ }
+
+ // Check if a string is contained inside the property
+ public boolean checkProperty(String param) {
+ param = param.toLowerCase(Locale.ENGLISH);
+ for (String block : disabledAlgorithms) {
+ if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Check algorithm constraints with key and algorithm
private boolean checkConstraints(Set<CryptoPrimitive> primitives,
String algorithm, Key key, AlgorithmParameters parameters) {
@@ -128,7 +169,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
throw new IllegalArgumentException("The key cannot be null");
}
- // check the target algorithm
+ // check the signature algorithm
if (algorithm != null && algorithm.length() != 0) {
if (!permits(primitives, algorithm, parameters)) {
return false;
@@ -141,97 +182,203 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
}
// check the key constraints
- if (keySizeConstraints.disables(key)) {
- return false;
- }
-
- return true;
+ return algorithmConstraints.permits(key);
}
- private static KeySizeConstraints getKeySizeConstraints(
- String[] disabledAlgorithms, String propertyName) {
- synchronized (keySizeConstraintsMap) {
- if(!keySizeConstraintsMap.containsKey(propertyName)) {
- // map the key constraints
- KeySizeConstraints keySizeConstraints =
- new KeySizeConstraints(disabledAlgorithms);
- keySizeConstraintsMap.put(propertyName, keySizeConstraints);
- }
+ /*
+ * Check algorithm constraints with Certificate
+ * Uses new style permit() which throws exceptions.
+ */
+ private void checkConstraints(Set<CryptoPrimitive> primitives,
+ CertConstraintParameters cp) throws CertPathValidatorException {
+
+ X509Certificate cert = cp.getCertificate();
+ String algorithm = cert.getSigAlgName();
+
+ // Check signature algorithm is not disabled
+ if (!permits(primitives, algorithm, null)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on disabled "+
+ "signature algorithm: " + algorithm,
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
- return keySizeConstraintsMap.get(propertyName);
+ // Check key algorithm is not disabled
+ if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) {
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on disabled "+
+ "public key algorithm: " + algorithm,
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
}
+
+ // Check the certificate and key constraints
+ algorithmConstraints.permits(cp);
+
}
/**
- * key constraints
+ * Key and Certificate Constraints
+ *
+ * The complete disabling of an algorithm is not handled by Constraints or
+ * Constraint classes. That is addressed with
+ * permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
+ *
+ * When passing a Key to permit(), the boolean return values follow the
+ * same as the interface class AlgorithmConstraints.permit(). This is to
+ * maintain compatibility:
+ * 'true' means the operation is allowed.
+ * 'false' means it failed the constraints and is disallowed.
+ *
+ * When passing CertConstraintParameters through permit(), an exception
+ * will be thrown on a failure to better identify why the operation was
+ * disallowed.
*/
- private static class KeySizeConstraints {
- private static final Pattern pattern = Pattern.compile(
- "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
- private Map<String, Set<KeySizeConstraint>> constraintsMap =
- Collections.synchronizedMap(
- new HashMap<String, Set<KeySizeConstraint>>());
+ private static class Constraints {
+ private Map<String, Set<Constraint>> constraintsMap = new HashMap<>();
+ private static final Pattern keySizePattern = Pattern.compile(
+ "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
- public KeySizeConstraints(String[] restrictions) {
- for (String restriction : restrictions) {
- if (restriction == null || restriction.isEmpty()) {
+ public Constraints(String[] constraintArray) {
+ for (String constraintEntry : constraintArray) {
+ if (constraintEntry == null || constraintEntry.isEmpty()) {
continue;
}
- Matcher matcher = pattern.matcher(restriction);
- if (matcher.matches()) {
- String algorithm = matcher.group(1);
+ constraintEntry = constraintEntry.trim();
+ if (debug != null) {
+ debug.println("Constraints: " + constraintEntry);
+ }
+
+ // Check if constraint is a complete disabling of an
+ // algorithm or has conditions.
+ String algorithm;
+ String policy;
+ int space = constraintEntry.indexOf(' ');
+ if (space > 0) {
+ algorithm = AlgorithmDecomposer.hashName(
+ constraintEntry.substring(0, space).
+ toUpperCase(Locale.ENGLISH));
+ policy = constraintEntry.substring(space + 1);
+ } else {
+ constraintsMap.putIfAbsent(
+ constraintEntry.toUpperCase(Locale.ENGLISH),
+ new HashSet<>());
+ continue;
+ }
- KeySizeConstraint.Operator operator =
- KeySizeConstraint.Operator.of(matcher.group(2));
- int length = Integer.parseInt(matcher.group(3));
+ // Convert constraint conditions into Constraint classes
+ Constraint c = null;
+ Constraint lastConstraint = null;
+ // Allow only one jdkCA entry per constraint entry
+ boolean jdkCALimit = false;
- algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+ for (String entry : policy.split("&")) {
+ entry = entry.trim();
- synchronized (constraintsMap) {
- if (!constraintsMap.containsKey(algorithm)) {
- constraintsMap.put(algorithm,
- new HashSet<KeySizeConstraint>());
+ Matcher matcher = keySizePattern.matcher(entry);
+ if (matcher.matches()) {
+ if (debug != null) {
+ debug.println("Constraints set to keySize: " +
+ entry);
}
+ c = new KeySizeConstraint(algorithm,
+ KeySizeConstraint.Operator.of(matcher.group(1)),
+ Integer.parseInt(matcher.group(2)));
- Set<KeySizeConstraint> constraintSet =
- constraintsMap.get(algorithm);
- KeySizeConstraint constraint =
- new KeySizeConstraint(operator, length);
- constraintSet.add(constraint);
+ } else if (entry.equalsIgnoreCase("jdkCA")) {
+ if (debug != null) {
+ debug.println("Constraints set to jdkCA.");
+ }
+ if (jdkCALimit) {
+ throw new IllegalArgumentException("Only one " +
+ "jdkCA entry allowed in property. " +
+ "Constraint: " + constraintEntry);
+ }
+ c = new jdkCAConstraint(algorithm);
+ jdkCALimit = true;
}
- }
- }
- }
- // Does this KeySizeConstraints disable the specified key?
- public boolean disables(Key key) {
- String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
- synchronized (constraintsMap) {
- if (constraintsMap.containsKey(algorithm)) {
- Set<KeySizeConstraint> constraintSet =
- constraintsMap.get(algorithm);
- for (KeySizeConstraint constraint : constraintSet) {
- if (constraint.disables(key)) {
- return true;
+ // Link multiple conditions for a single constraint
+ // into a linked list.
+ if (lastConstraint == null) {
+ if (!constraintsMap.containsKey(algorithm)) {
+ constraintsMap.putIfAbsent(algorithm,
+ new HashSet<>());
+ }
+ if (c != null) {
+ constraintsMap.get(algorithm).add(c);
}
+ } else {
+ lastConstraint.nextConstraint = c;
}
+ lastConstraint = c;
}
}
+ }
+
+ // Get applicable constraints based off the signature algorithm
+ private Set<Constraint> getConstraints(String algorithm) {
+ return constraintsMap.get(algorithm);
+ }
+ // Check if KeySizeConstraints permit the specified key
+ public boolean permits(Key key) {
+ Set<Constraint> set = getConstraints(key.getAlgorithm());
+ if (set == null) {
+ return true;
+ }
+ for (Constraint constraint : set) {
+ if (!constraint.permits(key)) {
+ if (debug != null) {
+ debug.println("keySizeConstraint: failed key " +
+ "constraint check " + KeyUtil.getKeySize(key));
+ }
return false;
}
+ }
+ return true;
}
- /**
- * Key size constraint.
- *
- * e.g. "keysize <= 1024"
- */
- private static class KeySizeConstraint {
+ // Check if constraints permit this cert.
+ public void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException {
+ X509Certificate cert = cp.getCertificate();
+
+ if (debug != null) {
+ debug.println("Constraints.permits(): " + cert.getSigAlgName());
+ }
+
+ // Get all signature algorithms to check for constraints
+ Set<String> algorithms =
+ AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName());
+ if (algorithms == null || algorithms.isEmpty()) {
+ return;
+ }
+
+ // Attempt to add the public key algorithm to the set
+ algorithms.add(cert.getPublicKey().getAlgorithm());
+
+ // Check all applicable constraints
+ for (String algorithm : algorithms) {
+ Set<Constraint> set = getConstraints(algorithm);
+ if (set == null) {
+ continue;
+ }
+ for (Constraint constraint : set) {
+ constraint.permits(cp);
+ }
+ }
+ }
+ }
+
+ // Abstract class for algorithm constraint checking
+ private abstract static class Constraint {
+ String algorithm;
+ Constraint nextConstraint = null;
+
// operator
- static enum Operator {
+ enum Operator {
EQ, // "=="
NE, // "!="
LT, // "<"
@@ -255,16 +402,77 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
return GE;
}
- throw new IllegalArgumentException(
- s + " is not a legal Operator");
+ throw new IllegalArgumentException("Error in security " +
+ "property. " + s + " is not a legal Operator");
}
}
+ /**
+ * Check if an algorithm constraint permit this key to be used.
+ * @param key Public key
+ * @return true if constraints do not match
+ */
+ public boolean permits(Key key) {
+ return true;
+ }
+
+ /**
+ * Check if an algorithm constraint is permit this certificate to
+ * be used.
+ * @param cp CertificateParameter containing certificate and state info
+ * @return true if constraints do not match
+ */
+ public abstract void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException;
+ }
+
+ /*
+ * This class contains constraints dealing with the certificate chain
+ * of the certificate.
+ */
+ private static class jdkCAConstraint extends Constraint {
+ jdkCAConstraint(String algo) {
+ algorithm = algo;
+ }
+
+ /*
+ * Check if each constraint fails and check if there is a linked
+ * constraint Any permitted constraint will exit the linked list
+ * to allow the operation.
+ */
+ public void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException {
+ if (debug != null) {
+ debug.println("jdkCAConstraints.permits(): " + algorithm);
+ }
+
+ // Return false if the chain has a trust anchor in cacerts
+ if (cp.isTrustedMatch()) {
+ if (nextConstraint != null) {
+ nextConstraint.permits(cp);
+ return;
+ }
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on certificate " +
+ "anchor limits",
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
+ }
+ }
+
+
+ /*
+ * This class contains constraints dealing with the key size
+ * support limits per algorithm. e.g. "keySize <= 1024"
+ */
+ private static class KeySizeConstraint extends Constraint {
+
private int minSize; // the minimal available key size
private int maxSize; // the maximal available key size
private int prohibitedSize = -1; // unavailable key sizes
- public KeySizeConstraint(Operator operator, int length) {
+ public KeySizeConstraint(String algo, Operator operator, int length) {
+ algorithm = algo;
switch (operator) {
case EQ: // an unavailable key size
this.minSize = 0;
@@ -298,21 +506,59 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
}
}
- // Does this key constraint disable the specified key?
- public boolean disables(Key key) {
- int size = KeyUtil.getKeySize(key);
+ /*
+ * If we are passed a certificate, extract the public key and use it.
+ *
+ * Check if each constraint fails and check if there is a linked
+ * constraint Any permitted constraint will exit the linked list
+ * to allow the operation.
+ */
+ public void permits(CertConstraintParameters cp)
+ throws CertPathValidatorException {
+ if (!permitsImpl(cp.getCertificate().getPublicKey())) {
+ if (nextConstraint != null) {
+ nextConstraint.permits(cp);
+ return;
+ }
+ throw new CertPathValidatorException(
+ "Algorithm constraints check failed on keysize limits",
+ null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+ }
+ }
+
+ // Check if key constraint disable the specified key
+ // Uses old style permit()
+ public boolean permits(Key key) {
+ // If we recursively find a constraint that permits us to use
+ // this key, return true and skip any other constraint checks.
+ if (nextConstraint != null && nextConstraint.permits(key)) {
+ return true;
+ }
+ if (debug != null) {
+ debug.println("KeySizeConstraints.permits(): " + algorithm);
+ }
+
+ return permitsImpl(key);
+ }
+
+ private boolean permitsImpl(Key key) {
+ // Verify this constraint is for this public key algorithm
+ if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
+ return true;
+ }
+
+ int size = KeyUtil.getKeySize(key);
if (size == 0) {
- return true; // we don't allow any key of size 0.
+ return false; // we don't allow any key of size 0.
} else if (size > 0) {
- return ((size < minSize) || (size > maxSize) ||
+ return !((size < minSize) || (size > maxSize) ||
(prohibitedSize == size));
} // Otherwise, the key size is not accessible. Conservatively,
// please don't disable such keys.
- return false;
+ return true;
+ }
}
}
-}
-
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/KeyUtil.java b/openjdk/jdk/src/share/classes/sun/security/util/KeyUtil.java
index 67a9e45..9a4d0b4 100644
--- openjdk/jdk/src/share/classes/sun/security/util/KeyUtil.java
+++ openjdk/jdk/src/share/classes/sun/security/util/KeyUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@ import java.security.InvalidKeyException;
import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;
import java.security.interfaces.DSAKey;
+import java.security.interfaces.DSAParams;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.SecretKey;
@@ -87,7 +88,8 @@ public final class KeyUtil {
size = pubk.getParams().getOrder().bitLength();
} else if (key instanceof DSAKey) {
DSAKey pubk = (DSAKey)key;
- size = pubk.getParams().getP().bitLength();
+ DSAParams params = pubk.getParams(); // params can be null
+ size = (params != null) ? params.getP().bitLength() : -1;
} else if (key instanceof DHKey) {
DHKey pubk = (DHKey)key;
size = pubk.getParams().getP().bitLength();
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java b/openjdk/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java
index 106ec78..ea688da 100644
--- openjdk/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java
+++ openjdk/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@ package sun.security.util;
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
import java.security.Key;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Set;
import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms;
@@ -42,15 +40,12 @@ public class LegacyAlgorithmConstraints extends AbstractAlgorithmConstraints {
public final static String PROPERTY_TLS_LEGACY_ALGS =
"jdk.tls.legacyAlgorithms";
- private final static Map<String, String[]> legacyAlgorithmsMap =
- new HashMap<>();
-
private final String[] legacyAlgorithms;
public LegacyAlgorithmConstraints(String propertyName,
AlgorithmDecomposer decomposer) {
super(decomposer);
- legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName);
+ legacyAlgorithms = getAlgorithms(propertyName);
}
@Override
diff --git a/openjdk/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java b/openjdk/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
index 66038a3..97dc9c5 100644
--- openjdk/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
+++ openjdk/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
@@ -255,7 +255,13 @@ class ObjectIdentifier implements Serializable
+ " (tag = " + type_id + ")"
);
- encoding = new byte[in.getLength()];
+ int len = in.getLength();
+ if (len > in.available()) {
+ throw new IOException("ObjectIdentifier() -- length exceeds" +
+ "data available. Length: " + len + ", Available: " +
+ in.available());
+ }
+ encoding = new byte[len];
in.getBytes(encoding);
check(encoding);
}
diff --git a/openjdk/jdk/src/share/classes/sun/security/x509/X509CertImpl.java b/openjdk/jdk/src/share/classes/sun/security/x509/X509CertImpl.java
index fdbdd3c..ab1c450 100644
--- openjdk/jdk/src/share/classes/sun/security/x509/X509CertImpl.java
+++ openjdk/jdk/src/share/classes/sun/security/x509/X509CertImpl.java
@@ -1932,18 +1932,19 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
public String getFingerprint(String algorithm) {
return fingerprints.computeIfAbsent(algorithm,
- x -> getCertificateFingerPrint(x));
+ x -> getFingerprint(x, this));
}
/**
* Gets the requested finger print of the certificate. The result
* only contains 0-9 and A-F. No small case, no colon.
*/
- private String getCertificateFingerPrint(String mdAlg) {
+ public static String getFingerprint(String algorithm,
+ X509Certificate cert) {
String fingerPrint = "";
try {
- byte[] encCertInfo = getEncoded();
- MessageDigest md = MessageDigest.getInstance(mdAlg);
+ byte[] encCertInfo = cert.getEncoded();
+ MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] digest = md.digest(encCertInfo);
StringBuffer buf = new StringBuffer();
for (int i = 0; i < digest.length; i++) {
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/openjdk/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
index 5722da9..e9459d9 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
@@ -188,6 +188,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
String MHT[] = new String[] {"Marshall Islands Time", "MHT",
"Marshall Islands Summer Time", "MHST",
"Marshall Islands Time", "MHT"};
+ String MMT[] = new String[] {"Myanmar Time", "MMT",
+ "Myanmar Summer Time", "MMST",
+ "Myanmar Time", "MMT"};
String MSK[] = new String[] {"Moscow Standard Time", "MSK",
"Moscow Daylight Time", "MSD",
"Moscow Time", "MT"};
@@ -683,9 +686,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Qyzylorda Time", "QYZT",
"Qyzylorda Summer Time", "QYZST",
"Qyzylorda Time", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Myanmar Time", "MMT",
- "Myanmar Summer Time", "MMST",
- "Myanmar Time", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Sakhalin Time", "SAKT",
@@ -718,6 +719,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
"Vladivostok Summer Time", "VLAST",
"Vladivostok Time", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Yekaterinburg Time", "YEKT",
"Yekaterinburg Summer Time", "YEKST",
"Yekaterinburg Time", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java b/openjdk/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
index 8fa22f9..9cdca7f 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
String MHT[] = new String[] {"Marshallinseln Zeit", "MHT",
"Marshallinseln Sommerzeit", "MHST",
"Marshallinseln Zeit", "MHT"};
+ String MMT[] = new String[] {"Myanmar Zeit", "MMT",
+ "Myanmar Sommerzeit", "MMST",
+ "Myanmar Zeit", "MMT"};
String MSK[] = new String[] {"Moskauer Normalzeit", "MSK",
"Moskauer Sommerzeit", "MSD",
"Zeitzone f\u00FCr Moskau", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Qyzylorda Zeit", "QYZT",
"Qyzylorda Sommerzeit", "QYZST",
"Qyzylorda Zeit", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Myanmar Zeit", "MMT",
- "Myanmar Sommerzeit", "MMST",
- "Myanmar Zeit", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Sakhalin Zeit", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
"Wladiwostok Sommerzeit", "VLAST",
"Wladiwostok Zeit", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Jekaterinburger Zeit", "YEKT",
"Jekaterinburger Sommerzeit", "YEKST",
"Jekaterinburger Zeit", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java b/openjdk/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
index c20c02e..1d41d22 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
String MHT[] = new String[] {"Hora de las Islas Marshall", "MHT",
"Hora de verano de las Islas Marshall", "MHST",
"Hora de Islas Marshall", "MHT"};
+ String MMT[] = new String[] {"Hora de Myanmar", "MMT",
+ "Hora de verano de Myanmar", "MMST",
+ "Hora de Myanmar", "MMT"};
String MSK[] = new String[] {"Hora est\u00e1ndar de Mosc\u00fa", "MSK",
"Hora de verano de Mosc\u00fa", "MSD",
"Hora de Mosc\u00FA", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Hora de Qyzylorda", "QYZT",
"Hora de verano de Qyzylorda", "QYZST",
"Hora de Qyzylorda", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Hora de Myanmar", "MMT",
- "Hora de verano de Myanmar", "MMST",
- "Hora de Myanmar", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Hora de Sajalin", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
"Hora de verano de Vladivostok", "VLAST",
"Hora de Vladivostok", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Hora de Ekaterinburgo", "YEKT",
"Hora de verano de Ekaterinburgo", "YEKST",
"Hora de Ekaterinburgo", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java b/openjdk/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
index 3d81200..5e3d2bc 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
String MHT[] = new String[] {"Heure des Iles Marshall", "MHT",
"Heure d'\u00e9t\u00e9 des Iles Marshall", "MHST",
"Heure des Iles Marshall", "MHT"};
+ String MMT[] = new String[] {"Heure de Myanmar", "MMT",
+ "Heure d'\u00e9t\u00e9 de Myanmar", "MMST",
+ "Heure de Myanmar", "MMT"};
String MSK[] = new String[] {"Heure standard de Moscou", "MSK",
"Heure avanc\u00e9e de Moscou", "MSD",
"Moscou", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Heure de Kyzylorda", "QYZT",
"Heure d'\u00e9t\u00e9 de Kyzylorda", "QYZST",
"Heure de Kyzylorda", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Heure de Myanmar", "MMT",
- "Heure d'\u00e9t\u00e9 de Myanmar", "MMST",
- "Heure de Myanmar", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Heure de Sakhalin", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
"Heure d'\u00e9t\u00e9 de Vladivostok", "VLAST",
"Heure de Vladivostok", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Heure de Yekaterinburg", "YEKT",
"Heure d'\u00e9t\u00e9 de Yekaterinburg", "YEKST",
"Heure de Yekaterinburg", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java b/openjdk/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
index 33350c4..49930fd 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
String MHT[] = new String[] {"Ora delle Isole Marshall", "MHT",
"Ora estiva delle Isole Marshall", "MHST",
"Ora delle Isole Marshall", "MHT"};
+ String MMT[] = new String[] {"Ora della Birmania/Myanmar", "MMT",
+ "Ora estiva della Birmania/Myanmar", "MMST",
+ "Ora della Birmania/Myanmar", "MMT"};
String MSK[] = new String[] {"Ora standard di Mosca", "MSK",
"Ora legale di Mosca", "MSD",
"Ora Mosca", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Ora di Qyzylorda", "QYZT",
"Ora estiva di Qyzylorda", "QYZST",
"Ora di Qyzylorda", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Ora della Birmania/Myanmar", "MMT",
- "Ora estiva della Birmania/Myanmar", "MMST",
- "Ora della Birmania/Myanmar", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Ora di Sakhalin", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
"Ora estiva di Vladivostok", "VLAST",
"Ora di Vladivostok", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Ora di Ekaterinburg", "YEKT",
"Ora estiva di Ekaterinburg", "YEKST",
"Ora di Ekaterinburg", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java b/openjdk/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
index 57a3fb7..90c26c0 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
String MHT[] = new String[] {"\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u6642\u9593", "MHT",
"\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u590f\u6642\u9593", "MHST",
"\u30DE\u30FC\u30B7\u30E3\u30EB\u8AF8\u5CF6\u6642\u9593", "MHT"};
+ String MMT[] = new String[] {"\u30df\u30e3\u30f3\u30de\u30fc\u6642\u9593", "MMT",
+ "\u30df\u30e3\u30f3\u30de\u30fc\u590f\u6642\u9593", "MMST",
+ "\u30DF\u30E3\u30F3\u30DE\u30FC\u6642\u9593", "MMT"};
String MSK[] = new String[] {"\u30e2\u30b9\u30af\u30ef\u6a19\u6e96\u6642", "MSK",
"\u30e2\u30b9\u30af\u30ef\u590f\u6642\u9593", "MSD",
"\u30E2\u30B9\u30AF\u30EF\u6642\u9593", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"\u30ad\u30b8\u30eb\u30aa\u30eb\u30c0\u6642\u9593", "QYZT",
"\u30ad\u30b8\u30eb\u30aa\u30eb\u30c0\u590f\u6642\u9593", "QYZST",
"\u30AF\u30BA\u30ED\u30EB\u30C0\u6642\u9593", "QYZT"}},
- {"Asia/Rangoon", new String[] {"\u30df\u30e3\u30f3\u30de\u30fc\u6642\u9593", "MMT",
- "\u30df\u30e3\u30f3\u30de\u30fc\u590f\u6642\u9593", "MMST",
- "\u30DF\u30E3\u30F3\u30DE\u30FC\u6642\u9593", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"\u6a3a\u592a\u6642\u9593", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
"\u30a6\u30e9\u30b8\u30aa\u30b9\u30c8\u30af\u590f\u6642\u9593", "VLAST",
"\u30A6\u30E9\u30B8\u30AA\u30B9\u30C8\u30AF\u6642\u9593", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"\u30a8\u30ab\u30c6\u30ea\u30f3\u30d6\u30eb\u30b0\u6642\u9593", "YEKT",
"\u30a8\u30ab\u30c6\u30ea\u30f3\u30d6\u30eb\u30b0\u590f\u6642\u9593", "YEKST",
"\u30A8\u30AB\u30C6\u30EA\u30F3\u30D6\u30EB\u30AF\u6642\u9593", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java b/openjdk/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
index d17154b..9aee59b 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
String MHT[] = new String[] {"\ub9c8\uc15c\uc81c\ub3c4 \uc2dc\uac04", "MHT",
"\ub9c8\uc15c\uc81c\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MHST",
"\uB9C8\uC15C \uC81C\uB3C4 \uD45C\uC900\uC2DC", "MHT"};
+ String MMT[] = new String[] {"\ubbf8\uc580\ub9c8 \uc2dc\uac04", "MMT",
+ "\ubbf8\uc580\ub9c8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MMST",
+ "\uBBF8\uC580\uB9C8 \uD45C\uC900\uC2DC", "MMT"};
String MSK[] = new String[] {"\ubaa8\uc2a4\ud06c\ubc14 \ud45c\uc900\uc2dc", "MSK",
"\ubaa8\uc2a4\ud06c\ubc14 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MSD",
"\uBAA8\uC2A4\uD06C\uBC14 \uD45C\uC900\uC2DC", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Qyzylorda \ud45c\uc900\uc2dc", "QYZT",
"Qyzylorda \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "QYZST",
"\uD0A4\uC9C8\uB85C\uB974\uB2E4 \uD45C\uC900\uC2DC", "QYZT"}},
- {"Asia/Rangoon", new String[] {"\ubbf8\uc580\ub9c8 \uc2dc\uac04", "MMT",
- "\ubbf8\uc580\ub9c8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MMST",
- "\uBBF8\uC580\uB9C8 \uD45C\uC900\uC2DC", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"\uc0ac\ud560\ub9b0 \uc2dc\uac04", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
"\ube14\ub77c\ub514\ubcf4\uc2a4\ud1a1 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VLAST",
"\uBE14\uB77C\uB514\uBCF4\uC2A4\uD1A1 \uD45C\uC900\uC2DC", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"\uc608\uce74\ud14c\ub9b0\ubc84\uadf8 \uc2dc\uac04", "YEKT",
"\uc608\uce74\ud14c\ub9b0\ubc84\uadf8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "YEKST",
"\uC608\uCE74\uD14C\uB9B0\uBD80\uB974\uD06C \uD45C\uC900\uC2DC", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java b/openjdk/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
index 32747fe..ec3afb5 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
String MSK[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Moscou", "MSK",
"Hor\u00e1rio de luz natural de Moscou", "MSD",
"Hor\u00E1rio de Moscou", "MT"};
+ String MMT[] = new String[] {"Fuso hor\u00e1rio de Mianmar", "MMT",
+ "Fuso hor\u00e1rio de ver\u00e3o de Mianmar", "MMST",
+ "Hor\u00E1rio de Mianmar", "MMT"};
String MST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o das montanhas", "MST",
"Hor\u00e1rio de luz natural das montanhas", "MDT",
"Hor\u00E1rio das Montanhas Rochosas", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Fuso hor\u00e1rio de Kizil-Orda", "QYZT",
"Fuso hor\u00e1rio de ver\u00e3o de Kizil-Orda", "QYZST",
"Hor\u00E1rio de Qyzylorda", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Fuso hor\u00e1rio de Mianmar", "MMT",
- "Fuso hor\u00e1rio de ver\u00e3o de Mianmar", "MMST",
- "Hor\u00E1rio de Mianmar", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Fuso hor\u00e1rio de Sakhalina", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
"Fuso hor\u00e1rio de ver\u00e3o de Vladivostok", "VLAST",
"Hor\u00E1rio de Vladivostok", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Fuso hor\u00e1rio de Yekaterinburgo", "YEKT",
"Fuso hor\u00e1rio de ver\u00e3o de Yekaterinburgo", "YEKST",
"Hor\u00E1rio de Yekaterinburg", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java b/openjdk/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
index 8705bfe..903902d 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
String MHT[] = new String[] {"Marshall\u00f6arna, normaltid", "MHT",
"Marshall\u00f6arna, sommartid", "MHST",
"Marshall\u00F6arna-tid", "MHT"};
+ String MMT[] = new String[] {"Myanmar, normaltid", "MMT",
+ "Myanmar, sommartid", "MMST",
+ "Myanmar-tid", "MMT"};
String MSK[] = new String[] {"Moskva, normaltid", "MSK",
"Moskva, sommartid", "MSD",
"Moskvas tid", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Qyzylorda, normaltid", "QYZT",
"Qyzylorda, sommartid", "QYZST",
"Qyzylorda-tid", "QYZT"}},
- {"Asia/Rangoon", new String[] {"Myanmar, normaltid", "MMT",
- "Myanmar, sommartid", "MMST",
- "Myanmar-tid", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"Sakhalin, normaltid", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
"Vladivostok, sommartid", "VLAST",
"Vladivostok-tid", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Jekaterinburg, normaltid", "YEKT",
"Jekaterinburg, sommartid", "YEKST",
"Jekaterinburg-tid", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java b/openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
index d5e5215..d2ef55b 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
String MHT[] = new String[] {"\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u65f6\u95f4", "MHT",
"\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u590f\u4ee4\u65f6", "MHST",
"\u9A6C\u7ECD\u5C14\u7FA4\u5C9B\u65F6\u95F4", "MHT"};
+ String MMT[] = new String[] {"\u7f05\u7538\u65f6\u95f4", "MMT",
+ "\u7f05\u7538\u590f\u4ee4\u65f6", "MMST",
+ "\u7F05\u7538\u65F6\u95F4", "MMT"};
String MSK[] = new String[] {"\u83ab\u65af\u79d1\u6807\u51c6\u65f6\u95f4", "MSK",
"\u83ab\u65af\u79d1\u590f\u4ee4\u65f6", "MSD",
"\u83AB\u65AF\u79D1\u65F6\u95F4", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Qyzylorda \u65f6\u95f4", "QYZT",
"Qyzylorda \u590f\u4ee4\u65f6", "QYZST",
"Qyzylorda \u65F6\u95F4", "QYZT"}},
- {"Asia/Rangoon", new String[] {"\u7f05\u7538\u65f6\u95f4", "MMT",
- "\u7f05\u7538\u590f\u4ee4\u65f6", "MMST",
- "\u7F05\u7538\u65F6\u95F4", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"\u5e93\u9875\u5c9b\u65f6\u95f4", "SAKT",
@@ -719,6 +720,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
"\u6d77\u53c2\u5d34\u590f\u4ee4\u65f6", "VLAST",
"\u6D77\u53C2\u5D34\u65F6\u95F4", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Yekaterinburg \u65f6\u95f4", "YEKT",
"Yekaterinburg \u590f\u4ee4\u65f6", "YEKST",
"Yekaterinburg \u65F6\u95F4", "YEKT"}},
diff --git a/openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java b/openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
index 4dc212b..b99f9d5 100644
--- openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
+++ openjdk/jdk/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
@@ -189,6 +189,9 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
String MHT[] = new String[] {"\u99ac\u7d39\u723e\u7fa4\u5cf6\u6642\u9593", "MHT",
"\u99ac\u7d39\u723e\u7fa4\u5cf6\u590f\u4ee4\u6642\u9593", "MHST",
"\u99AC\u7D39\u723E\u7FA4\u5CF6\u6642\u9593", "MHT"};
+ String MMT[] = new String[] {"\u7dec\u7538\u6642\u9593", "MMT",
+ "\u7dec\u7538\u590f\u4ee4\u6642\u9593", "MMST",
+ "\u7DEC\u7538\u6642\u9593", "MMT"};
String MSK[] = new String[] {"\u83ab\u65af\u79d1\u6a19\u6e96\u6642\u9593", "MSK",
"\u83ab\u65af\u79d1\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "MSD",
"\u83AB\u65AF\u79D1\u6642\u9593", "MT"};
@@ -684,9 +687,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"Asia/Qyzylorda", new String[] {"Qyzylorda \u6642\u9593", "QYZT",
"Qyzylorda \u590f\u4ee4\u6642\u9593", "QYZST",
"\u514B\u5B5C\u6D1B\u723E\u9054\u6642\u9593", "QYZT"}},
- {"Asia/Rangoon", new String[] {"\u7dec\u7538\u6642\u9593", "MMT",
- "\u7dec\u7538\u590f\u4ee4\u6642\u9593", "MMST",
- "\u7DEC\u7538\u6642\u9593", "MMT"}},
+ {"Asia/Rangoon", MMT},
{"Asia/Riyadh", ARAST},
{"Asia/Saigon", ICT},
{"Asia/Sakhalin", new String[] {"\u5eab\u9801\u5cf6\u6642\u9593", "SAKT",
@@ -721,6 +722,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
"\u6d77\u53c3\u5d34\u590f\u4ee4\u6642\u9593", "VLAST",
"\u6D77\u53C3\u5D34\u6642\u9593", "VLAT"}},
{"Asia/Yakutsk", YAKT},
+ {"Asia/Yangon", MMT},
{"Asia/Yekaterinburg", new String[] {"Yekaterinburg \u6642\u9593", "YEKT",
"Yekaterinburg \u590f\u4ee4\u6642\u9593", "YEKST",
"\u8449\u5361\u6377\u7433\u5821\u6642\u9593", "YEKT"}},
diff --git a/openjdk/jdk/src/share/lib/security/java.security-aix b/openjdk/jdk/src/share/lib/security/java.security-aix
index ae47914..8f9cf76 100644
--- openjdk/jdk/src/share/lib/security/java.security-aix
+++ openjdk/jdk/src/share/lib/security/java.security-aix
@@ -429,13 +429,13 @@ krb5.kdc.bad.policy = tryLast
# " DisabledAlgorithm { , DisabledAlgorithm } "
#
# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+# AlgorithmName [Constraint] { '&' Constraint }
#
# AlgorithmName:
# (see below)
#
# Constraint:
-# KeySizeConstraint
+# KeySizeConstraint, CertConstraint
#
# KeySizeConstraint:
# keySize Operator DecimalInteger
@@ -452,6 +452,9 @@ krb5.kdc.bad.policy = tryLast
# DecimalDigit: one of
# 1 2 3 4 5 6 7 8 9 0
#
+# CertConstraint
+# jdkCA
+#
# The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
# Documentation" for information about Standard Algorithm Names. Matching
@@ -474,6 +477,29 @@ krb5.kdc.bad.policy = tryLast
# be disabled. Note that the "KeySizeConstraint" only makes sense to key
# algorithms.
#
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+# "jdkCA" prohibits the specified algorithm only if the algorithm is used
+# in a certificate chain that terminates at a marked trust anchor in the
+# lib/security/cacerts keystore. All other chains are not affected.
+# If the jdkCA constraint is not set, then all chains using the
+# specified algorithm are restricted. jdkCA may only be used once in
+# a DisabledAlgorithm expression.
+# Example: To apply this constraint to SHA-1 certificates, include
+# the following "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'. For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint: "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property. This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm. For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
# Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations.
#
@@ -481,7 +507,45 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
#
#
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+ DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation. For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm. This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+# DisabledAlgorithms:
+# " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+# DisabledAlgorithm:
+# AlgorithmName [Constraint]
+#
+# AlgorithmName:
+# (see below)
+#
+# Constraint:
+# KeySizeConstraint
+#
+# KeySizeConstraint:
+# keySize Operator KeyLength
+#
+# Operator:
+# <= | < | == | != | >= | >
+#
+# KeyLength:
+# Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing
@@ -504,12 +568,13 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+ EC keySize < 224
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
@@ -523,7 +588,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -553,7 +618,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# See SSL/TLS specifications and "Java Cryptography Architecture Standard
# Algorithm Name Documentation" for information about the algorithm names.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -566,7 +631,8 @@ jdk.tls.legacyAlgorithms= \
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -625,39 +691,111 @@ jdk.tls.legacyAlgorithms= \
# EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
# FFFFFFFF FFFFFFFF, 2}
-# Algorithm restrictions for signed JAR files
#
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation. For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm. This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
#
-# The syntax of the disabled algorithm string is described as follows:
-# DisabledAlgorithms:
-# " DisabledAlgorithm { , DisabledAlgorithm } "
+# Policy:
+# Constraint {"," Constraint }
+# Constraint:
+# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+# AlgConstraint
+# "disallowAlg" Uri
+# MaxTransformsConstraint:
+# "maxTransforms" Integer
+# MaxReferencesConstraint:
+# "maxReferences" Integer
+# ReferenceUriSchemeConstraint:
+# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
+# OtherConstraint:
+# "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
#
-# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+jdk.xml.dsig.secureValidationPolicy=\
+ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+ maxTransforms 5,\
+ maxReferences 30,\
+ disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
+ noDuplicateIds,\
+ noRetrievalMethodLoops
+
#
-# AlgorithmName:
-# (see below)
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+# maxdepth=value - the maximum depth of a graph
+# maxrefs=value - the maximum number of internal references
+# maxbytes=value - the maximum number of bytes in the input stream
+# maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+# is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
#
-# Constraint:
-# KeySizeConstraint
+# RMI Registry Serial Filter
#
-# KeySizeConstraint:
-# keySize Operator KeyLength
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
#
-# Operator:
-# <= | < | == | != | >= | >
+#sun.rmi.registry.registryFilter=pattern;pattern
+
#
-# KeyLength:
-# Integer value of the algorithm's key length in bits
+# RMI Distributed Garbage Collector (DGC) Serial Filter
#
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
#
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
diff --git a/openjdk/jdk/src/share/lib/security/java.security-linux b/openjdk/jdk/src/share/lib/security/java.security-linux
index ae47914..fb18f70 100644
--- openjdk/jdk/src/share/lib/security/java.security-linux
+++ openjdk/jdk/src/share/lib/security/java.security-linux
@@ -429,13 +429,13 @@ krb5.kdc.bad.policy = tryLast
# " DisabledAlgorithm { , DisabledAlgorithm } "
#
# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+# AlgorithmName [Constraint] { '&' Constraint }
#
# AlgorithmName:
# (see below)
#
# Constraint:
-# KeySizeConstraint
+# KeySizeConstraint, CertConstraint
#
# KeySizeConstraint:
# keySize Operator DecimalInteger
@@ -452,6 +452,9 @@ krb5.kdc.bad.policy = tryLast
# DecimalDigit: one of
# 1 2 3 4 5 6 7 8 9 0
#
+# CertConstraint
+# jdkCA
+#
# The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
# Documentation" for information about Standard Algorithm Names. Matching
@@ -474,6 +477,29 @@ krb5.kdc.bad.policy = tryLast
# be disabled. Note that the "KeySizeConstraint" only makes sense to key
# algorithms.
#
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+# "jdkCA" prohibits the specified algorithm only if the algorithm is used
+# in a certificate chain that terminates at a marked trust anchor in the
+# lib/security/cacerts keystore. All other chains are not affected.
+# If the jdkCA constraint is not set, then all chains using the
+# specified algorithm are restricted. jdkCA may only be used once in
+# a DisabledAlgorithm expression.
+# Example: To apply this constraint to SHA-1 certificates, include
+# the following: "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'. For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint: "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property. This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm. For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
# Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations.
#
@@ -481,7 +507,45 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
#
#
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+ DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation. For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm. This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+# DisabledAlgorithms:
+# " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+# DisabledAlgorithm:
+# AlgorithmName [Constraint]
+#
+# AlgorithmName:
+# (see below)
+#
+# Constraint:
+# KeySizeConstraint
+#
+# KeySizeConstraint:
+# keySize Operator KeyLength
+#
+# Operator:
+# <= | < | == | != | >= | >
+#
+# KeyLength:
+# Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing
@@ -504,12 +568,13 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+ EC keySize < 224
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
@@ -523,7 +588,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -553,7 +618,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# See SSL/TLS specifications and "Java Cryptography Architecture Standard
# Algorithm Name Documentation" for information about the algorithm names.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -566,7 +631,8 @@ jdk.tls.legacyAlgorithms= \
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -625,39 +691,111 @@ jdk.tls.legacyAlgorithms= \
# EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
# FFFFFFFF FFFFFFFF, 2}
-# Algorithm restrictions for signed JAR files
#
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation. For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm. This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
#
-# The syntax of the disabled algorithm string is described as follows:
-# DisabledAlgorithms:
-# " DisabledAlgorithm { , DisabledAlgorithm } "
+# Policy:
+# Constraint {"," Constraint }
+# Constraint:
+# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+# AlgConstraint
+# "disallowAlg" Uri
+# MaxTransformsConstraint:
+# "maxTransforms" Integer
+# MaxReferencesConstraint:
+# "maxReferences" Integer
+# ReferenceUriSchemeConstraint:
+# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
+# OtherConstraint:
+# "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
#
-# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+jdk.xml.dsig.secureValidationPolicy=\
+ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+ maxTransforms 5,\
+ maxReferences 30,\
+ disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
+ noDuplicateIds,\
+ noRetrievalMethodLoops
+
#
-# AlgorithmName:
-# (see below)
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+# maxdepth=value - the maximum depth of a graph
+# maxrefs=value - the maximum number of internal references
+# maxbytes=value - the maximum number of bytes in the input stream
+# maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+# is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
#
-# Constraint:
-# KeySizeConstraint
+# RMI Registry Serial Filter
#
-# KeySizeConstraint:
-# keySize Operator KeyLength
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
#
-# Operator:
-# <= | < | == | != | >= | >
+#sun.rmi.registry.registryFilter=pattern;pattern
+
#
-# KeyLength:
-# Integer value of the algorithm's key length in bits
+# RMI Distributed Garbage Collector (DGC) Serial Filter
#
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
#
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
diff --git a/openjdk/jdk/src/share/lib/security/java.security-macosx b/openjdk/jdk/src/share/lib/security/java.security-macosx
index 2e25f91..ef02672 100644
--- openjdk/jdk/src/share/lib/security/java.security-macosx
+++ openjdk/jdk/src/share/lib/security/java.security-macosx
@@ -432,13 +432,13 @@ krb5.kdc.bad.policy = tryLast
# " DisabledAlgorithm { , DisabledAlgorithm } "
#
# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+# AlgorithmName [Constraint] { '&' Constraint }
#
# AlgorithmName:
# (see below)
#
# Constraint:
-# KeySizeConstraint
+# KeySizeConstraint, CertConstraint
#
# KeySizeConstraint:
# keySize Operator DecimalInteger
@@ -455,6 +455,9 @@ krb5.kdc.bad.policy = tryLast
# DecimalDigit: one of
# 1 2 3 4 5 6 7 8 9 0
#
+# CertConstraint
+# jdkCA
+#
# The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
# Documentation" for information about Standard Algorithm Names. Matching
@@ -477,6 +480,29 @@ krb5.kdc.bad.policy = tryLast
# be disabled. Note that the "KeySizeConstraint" only makes sense to key
# algorithms.
#
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+# "jdkCA" prohibits the specified algorithm only if the algorithm is used
+# in a certificate chain that terminates at a marked trust anchor in the
+# lib/security/cacerts keystore. All other chains are not affected.
+# If the jdkCA constraint is not set, then all chains using the
+# specified algorithm are restricted. jdkCA may only be used once in
+# a DisabledAlgorithm expression.
+# Example: To apply this constraint to SHA-1 certificates, include
+# the following: "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'. For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint: "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property. This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm. For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
# Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations.
#
@@ -484,7 +510,45 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
#
#
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+ DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation. For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm. This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+# DisabledAlgorithms:
+# " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+# DisabledAlgorithm:
+# AlgorithmName [Constraint]
+#
+# AlgorithmName:
+# (see below)
+#
+# Constraint:
+# KeySizeConstraint
+#
+# KeySizeConstraint:
+# keySize Operator KeyLength
+#
+# Operator:
+# <= | < | == | != | >= | >
+#
+# KeyLength:
+# Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing
@@ -507,12 +571,13 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+ EC keySize < 224
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
@@ -526,7 +591,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -556,7 +621,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# See SSL/TLS specifications and "Java Cryptography Architecture Standard
# Algorithm Name Documentation" for information about the algorithm names.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -569,7 +634,8 @@ jdk.tls.legacyAlgorithms= \
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -628,39 +694,111 @@ jdk.tls.legacyAlgorithms= \
# EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
# FFFFFFFF FFFFFFFF, 2}
-# Algorithm restrictions for signed JAR files
#
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation. For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm. This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
#
-# The syntax of the disabled algorithm string is described as follows:
-# DisabledAlgorithms:
-# " DisabledAlgorithm { , DisabledAlgorithm } "
+# Policy:
+# Constraint {"," Constraint }
+# Constraint:
+# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+# AlgConstraint
+# "disallowAlg" Uri
+# MaxTransformsConstraint:
+# "maxTransforms" Integer
+# MaxReferencesConstraint:
+# "maxReferences" Integer
+# ReferenceUriSchemeConstraint:
+# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
+# OtherConstraint:
+# "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
#
-# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+jdk.xml.dsig.secureValidationPolicy=\
+ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+ maxTransforms 5,\
+ maxReferences 30,\
+ disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
+ noDuplicateIds,\
+ noRetrievalMethodLoops
+
#
-# AlgorithmName:
-# (see below)
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+# maxdepth=value - the maximum depth of a graph
+# maxrefs=value - the maximum number of internal references
+# maxbytes=value - the maximum number of bytes in the input stream
+# maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+# is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
#
-# Constraint:
-# KeySizeConstraint
+# RMI Registry Serial Filter
#
-# KeySizeConstraint:
-# keySize Operator KeyLength
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
#
-# Operator:
-# <= | < | == | != | >= | >
+#sun.rmi.registry.registryFilter=pattern;pattern
+
#
-# KeyLength:
-# Integer value of the algorithm's key length in bits
+# RMI Distributed Garbage Collector (DGC) Serial Filter
#
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
#
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
diff --git a/openjdk/jdk/src/share/lib/security/java.security-solaris b/openjdk/jdk/src/share/lib/security/java.security-solaris
index 078fd66..537386c 100644
--- openjdk/jdk/src/share/lib/security/java.security-solaris
+++ openjdk/jdk/src/share/lib/security/java.security-solaris
@@ -431,13 +431,13 @@ krb5.kdc.bad.policy = tryLast
# " DisabledAlgorithm { , DisabledAlgorithm } "
#
# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+# AlgorithmName [Constraint] { '&' Constraint }
#
# AlgorithmName:
# (see below)
#
# Constraint:
-# KeySizeConstraint
+# KeySizeConstraint, CertConstraint
#
# KeySizeConstraint:
# keySize Operator DecimalInteger
@@ -454,6 +454,9 @@ krb5.kdc.bad.policy = tryLast
# DecimalDigit: one of
# 1 2 3 4 5 6 7 8 9 0
#
+# CertConstraint
+# jdkCA
+#
# The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
# Documentation" for information about Standard Algorithm Names. Matching
@@ -476,6 +479,29 @@ krb5.kdc.bad.policy = tryLast
# be disabled. Note that the "KeySizeConstraint" only makes sense to key
# algorithms.
#
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+# "jdkCA" prohibits the specified algorithm only if the algorithm is used
+# in a certificate chain that terminates at a marked trust anchor in the
+# lib/security/cacerts keystore. All other chains are not affected.
+# If the jdkCA constraint is not set, then all chains using the
+# specified algorithm are restricted. jdkCA may only be used once in
+# a DisabledAlgorithm expression.
+# Example: To apply this constraint to SHA-1 certificates, include
+# the following: "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'. For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint: "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property. This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm. For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
# Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations.
#
@@ -483,7 +509,45 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
#
#
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+ DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation. For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm. This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+# DisabledAlgorithms:
+# " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+# DisabledAlgorithm:
+# AlgorithmName [Constraint]
+#
+# AlgorithmName:
+# (see below)
+#
+# Constraint:
+# KeySizeConstraint
+#
+# KeySizeConstraint:
+# keySize Operator KeyLength
+#
+# Operator:
+# <= | < | == | != | >= | >
+#
+# KeyLength:
+# Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing
@@ -506,12 +570,13 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+ EC keySize < 224
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
@@ -525,7 +590,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -555,7 +620,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# See SSL/TLS specifications and "Java Cryptography Architecture Standard
# Algorithm Name Documentation" for information about the algorithm names.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -568,7 +633,8 @@ jdk.tls.legacyAlgorithms= \
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -627,39 +693,111 @@ jdk.tls.legacyAlgorithms= \
# EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
# FFFFFFFF FFFFFFFF, 2}
-# Algorithm restrictions for signed JAR files
#
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation. For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm. This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
#
-# The syntax of the disabled algorithm string is described as follows:
-# DisabledAlgorithms:
-# " DisabledAlgorithm { , DisabledAlgorithm } "
+# Policy:
+# Constraint {"," Constraint }
+# Constraint:
+# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+# AlgConstraint
+# "disallowAlg" Uri
+# MaxTransformsConstraint:
+# "maxTransforms" Integer
+# MaxReferencesConstraint:
+# "maxReferences" Integer
+# ReferenceUriSchemeConstraint:
+# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
+# OtherConstraint:
+# "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
#
-# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+jdk.xml.dsig.secureValidationPolicy=\
+ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+ maxTransforms 5,\
+ maxReferences 30,\
+ disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
+ noDuplicateIds,\
+ noRetrievalMethodLoops
+
#
-# AlgorithmName:
-# (see below)
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+# maxdepth=value - the maximum depth of a graph
+# maxrefs=value - the maximum number of internal references
+# maxbytes=value - the maximum number of bytes in the input stream
+# maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+# is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
#
-# Constraint:
-# KeySizeConstraint
+# RMI Registry Serial Filter
#
-# KeySizeConstraint:
-# keySize Operator KeyLength
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
#
-# Operator:
-# <= | < | == | != | >= | >
+#sun.rmi.registry.registryFilter=pattern;pattern
+
#
-# KeyLength:
-# Integer value of the algorithm's key length in bits
+# RMI Distributed Garbage Collector (DGC) Serial Filter
#
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
#
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
diff --git a/openjdk/jdk/src/share/lib/security/java.security-windows b/openjdk/jdk/src/share/lib/security/java.security-windows
index d2ddbe5..7bdda16 100644
--- openjdk/jdk/src/share/lib/security/java.security-windows
+++ openjdk/jdk/src/share/lib/security/java.security-windows
@@ -432,13 +432,13 @@ krb5.kdc.bad.policy = tryLast
# " DisabledAlgorithm { , DisabledAlgorithm } "
#
# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+# AlgorithmName [Constraint] { '&' Constraint }
#
# AlgorithmName:
# (see below)
#
# Constraint:
-# KeySizeConstraint
+# KeySizeConstraint, CertConstraint
#
# KeySizeConstraint:
# keySize Operator DecimalInteger
@@ -455,6 +455,9 @@ krb5.kdc.bad.policy = tryLast
# DecimalDigit: one of
# 1 2 3 4 5 6 7 8 9 0
#
+# CertConstraint
+# jdkCA
+#
# The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name
# Documentation" for information about Standard Algorithm Names. Matching
@@ -477,6 +480,29 @@ krb5.kdc.bad.policy = tryLast
# be disabled. Note that the "KeySizeConstraint" only makes sense to key
# algorithms.
#
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+# "jdkCA" prohibits the specified algorithm only if the algorithm is used
+# in a certificate chain that terminates at a marked trust anchor in the
+# lib/security/cacerts keystore. All other chains are not affected.
+# If the jdkCA constraint is not set, then all chains using the
+# specified algorithm are restricted. jdkCA may only be used once in
+# a DisabledAlgorithm expression.
+# Example: To apply this constraint to SHA-1 certificates, include
+# the following: "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'. For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint: "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property. This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm. For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
# Note: This property is currently used by Oracle's PKIX implementation. It
# is not guaranteed to be examined and used by other implementations.
#
@@ -484,7 +510,45 @@ krb5.kdc.bad.policy = tryLast
# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
#
#
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+ DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation. For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm. This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+# DisabledAlgorithms:
+# " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+# DisabledAlgorithm:
+# AlgorithmName [Constraint]
+#
+# AlgorithmName:
+# (see below)
+#
+# Constraint:
+# KeySizeConstraint
+#
+# KeySizeConstraint:
+# keySize Operator KeyLength
+#
+# Operator:
+# <= | < | == | != | >= | >
+#
+# KeyLength:
+# Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS) processing
@@ -507,12 +571,13 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
# See the specification of "jdk.certpath.disabledAlgorithms" for the
# syntax of the disabled algorithm string.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+ EC keySize < 224
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
@@ -526,7 +591,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -556,7 +621,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
# See SSL/TLS specifications and "Java Cryptography Architecture Standard
# Algorithm Name Documentation" for information about the algorithm names.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -569,7 +634,8 @@ jdk.tls.legacyAlgorithms= \
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -628,39 +694,111 @@ jdk.tls.legacyAlgorithms= \
# EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
# FFFFFFFF FFFFFFFF, 2}
-# Algorithm restrictions for signed JAR files
#
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation. For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm. This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
#
-# The syntax of the disabled algorithm string is described as follows:
-# DisabledAlgorithms:
-# " DisabledAlgorithm { , DisabledAlgorithm } "
+# Policy:
+# Constraint {"," Constraint }
+# Constraint:
+# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+# AlgConstraint
+# "disallowAlg" Uri
+# MaxTransformsConstraint:
+# "maxTransforms" Integer
+# MaxReferencesConstraint:
+# "maxReferences" Integer
+# ReferenceUriSchemeConstraint:
+# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
+# OtherConstraint:
+# "noDuplicateIds" | "noRetrievalMethodLoops"
+#
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
+#
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
#
-# DisabledAlgorithm:
-# AlgorithmName [Constraint]
+jdk.xml.dsig.secureValidationPolicy=\
+ disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+ disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+ maxTransforms 5,\
+ maxReferences 30,\
+ disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
+ noDuplicateIds,\
+ noRetrievalMethodLoops
+
#
-# AlgorithmName:
-# (see below)
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+# maxdepth=value - the maximum depth of a graph
+# maxrefs=value - the maximum number of internal references
+# maxbytes=value - the maximum number of bytes in the input stream
+# maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+# is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
#
-# Constraint:
-# KeySizeConstraint
+# RMI Registry Serial Filter
#
-# KeySizeConstraint:
-# keySize Operator KeyLength
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
#
-# Operator:
-# <= | < | == | != | >= | >
+#sun.rmi.registry.registryFilter=pattern;pattern
+
#
-# KeyLength:
-# Integer value of the algorithm's key length in bits
+# RMI Distributed Garbage Collector (DGC) Serial Filter
#
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
#
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
diff --git a/openjdk/jdk/src/solaris/native/java/net/SocketOutputStream.c b/openjdk/jdk/src/solaris/native/java/net/SocketOutputStream.c
index d6e01ff..16d68c2 100644
--- openjdk/jdk/src/solaris/native/java/net/SocketOutputStream.c
+++ openjdk/jdk/src/solaris/native/java/net/SocketOutputStream.c
@@ -103,31 +103,35 @@ Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
int llen = chunkLen;
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
- while(llen > 0) {
- int n = NET_Send(fd, bufP + loff, llen, 0);
- if (n > 0) {
- llen -= n;
- loff += n;
- continue;
- }
- if (n == JVM_IO_INTR) {
- JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
- } else {
- if (errno == ECONNRESET) {
- JNU_ThrowByName(env, "sun/net/ConnectionResetException",
- "Connection reset");
+ if ((*env)->ExceptionCheck(env)) {
+ break;
+ } else {
+ while(llen > 0) {
+ int n = NET_Send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
+ continue;
+ }
+ if (n == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
} else {
- NET_ThrowByNameWithLastError(env, "java/net/SocketException",
- "Write failed");
+ if (errno == ECONNRESET) {
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+ "Connection reset");
+ } else {
+ NET_ThrowByNameWithLastError(env, "java/net/SocketException",
+ "Write failed");
+ }
}
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- if (bufP != BUF) {
- free(bufP);
- }
- return;
+ len -= chunkLen;
+ off += chunkLen;
}
- len -= chunkLen;
- off += chunkLen;
}
if (bufP != BUF) {
diff --git a/openjdk/jdk/src/windows/native/java/net/Inet4AddressImpl.c b/openjdk/jdk/src/windows/native/java/net/Inet4AddressImpl.c
index f250c55..bfecffc 100644
--- openjdk/jdk/src/windows/native/java/net/Inet4AddressImpl.c
+++ openjdk/jdk/src/windows/native/java/net/Inet4AddressImpl.c
@@ -33,6 +33,7 @@
#include <process.h>
#include <iphlpapi.h>
#include <icmpapi.h>
+#include <WinError.h>
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
@@ -481,7 +482,15 @@ ping4(JNIEnv *env,
DWORD ReplySize = 0;
jboolean ret = JNI_FALSE;
- ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366051%28v=vs.85%29.aspx
+ ReplySize = sizeof(ICMP_ECHO_REPLY) // The buffer should be large enough
+ // to hold at least one ICMP_ECHO_REPLY
+ // structure
+ + sizeof(SendData) // plus RequestSize bytes of data.
+ + 8; // This buffer should also be large enough
+ // to also hold 8 more bytes of data
+ // (the size of an ICMP error message)
+
ReplyBuffer = (VOID*) malloc(ReplySize);
if (ReplyBuffer == NULL) {
IcmpCloseHandle(hIcmpFile);
@@ -517,10 +526,45 @@ ping4(JNIEnv *env,
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
}
- if (dwRetVal != 0) {
+ if (dwRetVal == 0) { // if the call failed
+ TCHAR *buf;
+ DWORD err = WSAGetLastError();
+ switch (err) {
+ case ERROR_NO_NETWORK:
+ case ERROR_NETWORK_UNREACHABLE:
+ case ERROR_HOST_UNREACHABLE:
+ case ERROR_PROTOCOL_UNREACHABLE:
+ case ERROR_PORT_UNREACHABLE:
+ case ERROR_REQUEST_ABORTED:
+ case ERROR_INCORRECT_ADDRESS:
+ case ERROR_HOST_DOWN:
+ case WSAEHOSTUNREACH: /* Host Unreachable */
+ case WSAENETUNREACH: /* Network Unreachable */
+ case WSAENETDOWN: /* Network is down */
+ case WSAEPFNOSUPPORT: /* Protocol Family unsupported */
+ case IP_REQ_TIMED_OUT:
+ break;
+ default:
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&buf, 0, NULL);
+ NET_ThrowNew(env, err, buf);
+ LocalFree(buf);
+ break;
+ }
+ } else {
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
- if ((int)pEchoReply->RoundTripTime <= timeout)
+
+ // This is to take into account the undocumented minimum
+ // timeout mentioned in the IcmpSendEcho call above.
+ // We perform an extra check to make sure that our
+ // roundtrip time was less than our desired timeout
+ // for cases where that timeout is < 1000ms.
+ if (pEchoReply->Status == IP_SUCCESS
+ && (int)pEchoReply->RoundTripTime <= timeout)
+ {
ret = JNI_TRUE;
+ }
}
free(ReplyBuffer);
diff --git a/openjdk/jdk/src/windows/native/java/net/SocketOutputStream.c b/openjdk/jdk/src/windows/native/java/net/SocketOutputStream.c
index 4bcfbc3..daec520 100644
--- openjdk/jdk/src/windows/native/java/net/SocketOutputStream.c
+++ openjdk/jdk/src/windows/native/java/net/SocketOutputStream.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -100,66 +100,69 @@ Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
int retry = 0;
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
-
- while(llen > 0) {
- int n = send(fd, bufP + loff, llen, 0);
- if (n > 0) {
- llen -= n;
- loff += n;
- continue;
- }
-
- /*
- * Due to a bug in Windows Sockets (observed on NT and Windows
- * 2000) it may be necessary to retry the send. The issue is that
- * on blocking sockets send/WSASend is supposed to block if there
- * is insufficient buffer space available. If there are a large
- * number of threads blocked on write due to congestion then it's
- * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
- * The workaround we use is to retry the send. If we have a
- * large buffer to send (>2k) then we retry with a maximum of
- * 2k buffer. If we hit the issue with <=2k buffer then we backoff
- * for 1 second and retry again. We repeat this up to a reasonable
- * limit before bailing out and throwing an exception. In load
- * conditions we've observed that the send will succeed after 2-3
- * attempts but this depends on network buffers associated with
- * other sockets draining.
- */
- if (WSAGetLastError() == WSAENOBUFS) {
- if (llen > MAX_BUFFER_LEN) {
- buflen = MAX_BUFFER_LEN;
- chunkLen = MAX_BUFFER_LEN;
- llen = MAX_BUFFER_LEN;
+ if ((*env)->ExceptionCheck(env)) {
+ break;
+ } else {
+ while(llen > 0) {
+ int n = send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
continue;
}
- if (retry >= 30) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "No buffer space available - exhausted attempts to queue buffer");
- if (bufP != BUF) {
- free(bufP);
+
+ /*
+ * Due to a bug in Windows Sockets (observed on NT and Windows
+ * 2000) it may be necessary to retry the send. The issue is that
+ * on blocking sockets send/WSASend is supposed to block if there
+ * is insufficient buffer space available. If there are a large
+ * number of threads blocked on write due to congestion then it's
+ * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
+ * The workaround we use is to retry the send. If we have a
+ * large buffer to send (>2k) then we retry with a maximum of
+ * 2k buffer. If we hit the issue with <=2k buffer then we backoff
+ * for 1 second and retry again. We repeat this up to a reasonable
+ * limit before bailing out and throwing an exception. In load
+ * conditions we've observed that the send will succeed after 2-3
+ * attempts but this depends on network buffers associated with
+ * other sockets draining.
+ */
+ if (WSAGetLastError() == WSAENOBUFS) {
+ if (llen > MAX_BUFFER_LEN) {
+ buflen = MAX_BUFFER_LEN;
+ chunkLen = MAX_BUFFER_LEN;
+ llen = MAX_BUFFER_LEN;
+ continue;
+ }
+ if (retry >= 30) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "No buffer space available - exhausted attempts to queue buffer");
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- return;
+ Sleep(1000);
+ retry++;
+ continue;
}
- Sleep(1000);
- retry++;
- continue;
- }
- /*
- * Send failed - can be caused by close or write error.
- */
- if (WSAGetLastError() == WSAENOTSOCK) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
- } else {
- NET_ThrowCurrent(env, "socket write error");
- }
- if (bufP != BUF) {
- free(bufP);
+ /*
+ * Send failed - can be caused by close or write error.
+ */
+ if (WSAGetLastError() == WSAENOTSOCK) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowCurrent(env, "socket write error");
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- return;
+ len -= chunkLen;
+ off += chunkLen;
}
- len -= chunkLen;
- off += chunkLen;
}
if (bufP != BUF) {
diff --git a/openjdk/jdk/src/windows/native/sun/security/mscapi/security.cpp b/openjdk/jdk/src/windows/native/sun/security/mscapi/security.cpp
index 553dd42..5796c30 100644
--- openjdk/jdk/src/windows/native/sun/security/mscapi/security.cpp
+++ openjdk/jdk/src/windows/native/sun/security/mscapi/security.cpp
@@ -352,38 +352,50 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateCh
BOOL bHasNoPrivateKey = FALSE;
DWORD dwPublicKeyLength = 0;
- if (::CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL,
- &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
+ // First, probe it silently
+ if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL,
+ &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
+ && GetLastError() != NTE_SILENT_CONTEXT)
{
bHasNoPrivateKey = TRUE;
+ }
+ else
+ {
+ if (bCallerFreeProv == TRUE) {
+ ::CryptReleaseContext(hCryptProv, NULL);
+ bCallerFreeProv = FALSE;
+ }
- } else {
- // Private key is available
-
- BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
-
- // Skip certificate if cannot find private key
- if (bGetUserKey == FALSE)
+ // Second, acquire the key normally (not silently)
+ if (::CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL,
+ &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
{
- if (bCallerFreeProv)
- ::CryptReleaseContext(hCryptProv, NULL);
-
- continue;
+ bHasNoPrivateKey = TRUE;
}
+ else
+ {
+ // Private key is available
+ BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey);
+
+ // Skip certificate if cannot find private key
+ if (bGetUserKey == FALSE) {
+ if (bCallerFreeProv)
+ ::CryptReleaseContext(hCryptProv, NULL);
+ continue;
+ }
- // Set cipher mode to ECB
- DWORD dwCipherMode = CRYPT_MODE_ECB;
- ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
-
-
- // If the private key is present in smart card, we may not be able to
- // determine the key length by using the private key handle. However,
- // since public/private key pairs must have the same length, we could
- // determine the key length of the private key by using the public key
- // in the certificate.
- dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
-
+ // Set cipher mode to ECB
+ DWORD dwCipherMode = CRYPT_MODE_ECB;
+ ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL);
+
+ // If the private key is present in smart card, we may not be able to
+ // determine the key length by using the private key handle. However,
+ // since public/private key pairs must have the same length, we could
+ // determine the key length of the private key by using the public key
+ // in the certificate.
+ dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
+ }
}
PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
@@ -392,8 +404,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateCh
//
if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
{
-
- for (unsigned int i=0; i < pCertChainContext->cChain; i++)
+ for (DWORD i = 0; i < pCertChainContext->cChain; i++)
{
// Found cert chain
PCERT_SIMPLE_CHAIN rgpChain =
@@ -443,6 +454,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_loadKeysOrCertificateCh
// cert collection
env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
}
+
if (bHasNoPrivateKey)
{
// Generate certificate chain and store into cert chain
@@ -1361,43 +1373,57 @@ JNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_getKeyFromCert
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwKeySpec;
+ BOOL bCallerFreeProv = FALSE;
+ BOOL bRes;
__try
{
if (usePrivateKey == JNI_TRUE) {
// Locate the key container for the certificate's private key
- if (!(::CryptAcquireCertificatePrivateKey(
- (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
- &dwKeySpec, NULL))) {
+ // First, probe it silently
+ bRes = ::CryptAcquireCertificatePrivateKey(
+ (PCCERT_CONTEXT) pCertContext, CRYPT_ACQUIRE_SILENT_FLAG,
+ NULL, &hCryptProv, &dwKeySpec, &bCallerFreeProv);
+
+ if (bRes == FALSE && GetLastError() != NTE_SILENT_CONTEXT)
+ {
+ ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
+ __leave;
+ }
+
+ if (bCallerFreeProv == TRUE) {
+ ::CryptReleaseContext(hCryptProv, NULL);
+ bCallerFreeProv = FALSE;
+ }
+
+ // Now, do it normally (not silently)
+ if (::CryptAcquireCertificatePrivateKey(
+ (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv,
+ &dwKeySpec, &bCallerFreeProv) == FALSE)
+ {
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
__leave;
}
// Get a handle to the private key
- if (!(::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))) {
+ if (::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey) == FALSE) {
ThrowException(env, KEY_EXCEPTION, GetLastError());
__leave;
}
-
- } else { // use public key
+ }
+ else // use public key
+ {
+ bCallerFreeProv = TRUE;
// Acquire a CSP context.
- if(::CryptAcquireContext(
- &hCryptProv,
- "J2SE",
- NULL,
- PROV_RSA_FULL,
- 0) == FALSE)
+ if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL,
+ PROV_RSA_FULL, 0) == FALSE)
{
// If CSP context hasn't been created, create one.
//
- if (::CryptAcquireContext(
- &hCryptProv,
- "J2SE",
- NULL,
- PROV_RSA_FULL,
- CRYPT_NEWKEYSET) == FALSE)
+ if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL,
+ PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE)
{
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
__leave;
@@ -1405,10 +1431,10 @@ JNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_getKeyFromCert
}
// Import the certificate's public key into the key container
- if (!(::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
- &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
- &hKey))) {
-
+ if (::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,
+ &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo),
+ &hKey) == FALSE)
+ {
ThrowException(env, KEY_EXCEPTION, GetLastError());
__leave;
}
@@ -1419,7 +1445,7 @@ JNIEXPORT jlong JNICALL Java_sun_security_mscapi_RSACipher_getKeyFromCert
//--------------------------------------------------------------------
// Clean up.
- if (hCryptProv)
+ if (bCallerFreeProv == TRUE && hCryptProv != NULL)
::CryptReleaseContext(hCryptProv, 0);
}
diff --git a/openjdk/jdk/src/windows/native/sun/windows/awt_Component.cpp b/openjdk/jdk/src/windows/native/sun/windows/awt_Component.cpp
index 0128972..9d239a0 100644
--- openjdk/jdk/src/windows/native/sun/windows/awt_Component.cpp
+++ openjdk/jdk/src/windows/native/sun/windows/awt_Component.cpp
@@ -98,7 +98,6 @@ BOOL AwtComponent::sm_restoreFocusAndActivation = FALSE;
HWND AwtComponent::sm_focusOwner = NULL;
HWND AwtComponent::sm_focusedWindow = NULL;
BOOL AwtComponent::sm_bMenuLoop = FALSE;
-AwtComponent* AwtComponent::sm_getComponentCache = NULL;
BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
/************************************************************************/
@@ -272,10 +271,6 @@ AwtComponent::~AwtComponent()
* handle.
*/
DestroyHWnd();
-
- if (sm_getComponentCache == this) {
- sm_getComponentCache = NULL;
- }
}
void AwtComponent::Dispose()
@@ -348,9 +343,6 @@ AwtComponent* AwtComponent::GetComponent(HWND hWnd) {
if (hWnd == AwtToolkit::GetInstance().GetHWnd()) {
return NULL;
}
- if (sm_getComponentCache && sm_getComponentCache->GetHWnd() == hWnd) {
- return sm_getComponentCache;
- }
// check that it's an AWT component from the same toolkit as the caller
if (::IsWindow(hWnd) &&
@@ -358,7 +350,7 @@ AwtComponent* AwtComponent::GetComponent(HWND hWnd) {
{
DASSERT(WmAwtIsComponent != 0);
if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) {
- return sm_getComponentCache = GetComponentImpl(hWnd);
+ return GetComponentImpl(hWnd);
}
}
return NULL;
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java b/openjdk/jdk/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java
new file mode 100644
index 0000000..802ccb3
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Security;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+/* @test
+ * @build CheckInputOrderTest SerialFilterTest
+ * @run testng/othervm CheckInputOrderTest
+ *
+ * @summary Test that when both global filter and specific filter are set,
+ * global filter will not affect specific filter.
+ */
+
+public class CheckInputOrderTest implements Serializable {
+ private static final long serialVersionUID = 12345678901L;
+
+ @DataProvider(name="Patterns")
+ Object[][] patterns() {
+ return new Object[][] {
+ new Object[] { SerialFilterTest.genTestObject("maxarray=1", true), "java.**;java.lang.*;java.lang.Long;maxarray=0", false },
+ new Object[] { SerialFilterTest.genTestObject("maxarray=1", true), "java.**;java.lang.*;java.lang.Long", true },
+ new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxdepth=0", false },
+ new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxbytes=0", false },
+ new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxrefs=0", false },
+
+ new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long", true },
+
+ new Object[] { Long.MAX_VALUE, "!java.**;java.lang.*;java.lang.Long", false },
+ new Object[] { Long.MAX_VALUE, "java.**;!java.lang.*;java.lang.Long", true },
+
+ new Object[] { Long.MAX_VALUE, "!java.lang.*;java.**;java.lang.Long", false },
+ new Object[] { Long.MAX_VALUE, "java.lang.*;!java.**;java.lang.Long", true },
+
+ new Object[] { Long.MAX_VALUE, "!java.lang.Long;java.**;java.lang.*", false },
+ new Object[] { Long.MAX_VALUE, "java.lang.Long;java.**;!java.lang.*", true },
+
+ new Object[] { Long.MAX_VALUE, "java.lang.Long;!java.**;java.lang.*", false },
+ new Object[] { Long.MAX_VALUE, "java.lang.Long;java.lang.Number;!java.**;java.lang.*", true },
+ };
+ }
+
+ /**
+ * Test:
+ * "global filter reject" + "specific ObjectInputStream filter is empty" => should reject
+ * "global filter reject" + "specific ObjectInputStream filter allow" => should allow
+ */
+ @Test(dataProvider="Patterns")
+ public void testRejectedInGlobal(Object toDeserialized, String pattern, boolean allowed) throws Exception {
+ byte[] bytes = SerialFilterTest.writeObjects(toDeserialized);
+ ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+ Object o = ois.readObject();
+ assertTrue(allowed, "filter should have thrown an exception");
+ } catch (InvalidClassException ice) {
+ assertFalse(allowed, "filter should have thrown an exception");
+ }
+ }
+}
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java b/openjdk/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java
new file mode 100644
index 0000000..7c03f91
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.security.AccessControlException;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+/* @test
+ * @build FilterWithSecurityManagerTest SerialFilterTest
+ * @run testng/othervm FilterWithSecurityManagerTest
+ * @run testng/othervm/policy=security.policy.without.globalFilter
+ * -Djava.security.manager=default FilterWithSecurityManagerTest
+ * @run testng/othervm/policy=security.policy
+ * -Djava.security.manager=default
+ * -Djdk.serialFilter=java.lang.Integer FilterWithSecurityManagerTest
+ *
+ * @summary Test that setting specific filter is checked by security manager,
+ * setting process-wide filter is checked by security manager.
+ */
+
+@Test
+public class FilterWithSecurityManagerTest {
+
+ byte[] bytes;
+ boolean setSecurityManager;
+ ObjectInputFilter filter;
+
+ @BeforeClass
+ public void setup() throws Exception {
+ setSecurityManager = System.getSecurityManager() != null;
+ Object toDeserialized = Long.MAX_VALUE;
+ bytes = SerialFilterTest.writeObjects(toDeserialized);
+ filter = ObjectInputFilter.Config.createFilter("java.lang.Long");
+ }
+
+ /**
+ * Test that setting process-wide filter is checked by security manager.
+ */
+ @Test
+ public void testGlobalFilter() throws Exception {
+ if (ObjectInputFilter.Config.getSerialFilter() == null) {
+ return;
+ }
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter.Config.setSerialFilter(filter);
+ assertFalse(setSecurityManager,
+ "When SecurityManager exists, without "
+ + "java.security.SerializablePermission(serialFilter) Exception should be thrown");
+ Object o = ois.readObject();
+ } catch (AccessControlException ex) {
+ assertTrue(setSecurityManager);
+ assertTrue(ex.getMessage().contains("java.io.SerializablePermission"));
+ assertTrue(ex.getMessage().contains("serialFilter"));
+ }
+ }
+
+ /**
+ * Test that setting specific filter is checked by security manager.
+ */
+ @Test(dependsOnMethods = { "testGlobalFilter" })
+ public void testSpecificFilter() throws Exception {
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+ Object o = ois.readObject();
+ } catch (AccessControlException ex) {
+ assertTrue(setSecurityManager);
+ assertTrue(ex.getMessage().contains("java.io.SerializablePermission"));
+ assertTrue(ex.getMessage().contains("serialFilter"));
+ }
+ }
+}
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java b/openjdk/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java
new file mode 100644
index 0000000..20503d1
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+
+import java.io.SerializablePermission;
+import java.security.Security;
+import java.util.Objects;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+import sun.misc.ObjectInputFilter;
+
+/* @test
+ * @build GlobalFilterTest SerialFilterTest
+ * @run testng/othervm GlobalFilterTest
+ * @run testng/othervm -Djdk.serialFilter=java.** GlobalFilterTest
+ * @run testng/othervm/policy=security.policy GlobalFilterTest
+ * @run testng/othervm/policy=security.policy
+ * -Djava.security.properties=${test.src}/java.security-extra1
+ * -Djava.security.debug=properties GlobalFilterTest
+ *
+ * @summary Test Global Filters
+ */
+@Test
+public class GlobalFilterTest {
+
+ /**
+ * DataProvider of patterns and objects derived from the configured process-wide filter.
+ * @return Array of arrays of pattern, object, allowed boolean, and API factory
+ */
+ @DataProvider(name="globalPatternElements")
+ Object[][] globalPatternElements() {
+ String globalFilter =
+ System.getProperty("jdk.serialFilter",
+ Security.getProperty("jdk.serialFilter"));
+ if (globalFilter == null) {
+ return new Object[0][];
+ }
+
+ String[] patterns = globalFilter.split(";");
+ Object[][] objects = new Object[patterns.length][];
+
+ for (int i = 0; i < patterns.length; i++) {
+ Object o;
+ boolean allowed;
+ String pattern = patterns[i].trim();
+ if (pattern.contains("=")) {
+ allowed = false;
+ o = SerialFilterTest.genTestObject(pattern, false);
+ } else {
+ allowed = !pattern.startsWith("!");
+ o = (allowed)
+ ? SerialFilterTest.genTestObject(pattern, true)
+ : SerialFilterTest.genTestObject(pattern.substring(1), false);
+
+ Assert.assertNotNull(o, "fail generation failed");
+ }
+ objects[i] = new Object[3];
+ objects[i][0] = pattern;
+ objects[i][1] = allowed;
+ objects[i][2] = o;
+ }
+ return objects;
+ }
+
+ /**
+ * Test that the process-wide filter is set when the properties are set
+ * and has the toString matching the configured pattern.
+ */
+ @Test()
+ static void globalFilter() {
+ String pattern =
+ System.getProperty("jdk.serialFilter",
+ Security.getProperty("jdk.serialFilter"));
+ ObjectInputFilter filter = ObjectInputFilter.Config.getSerialFilter();
+ System.out.printf("global pattern: %s, filter: %s%n", pattern, filter);
+ Assert.assertEquals(pattern, Objects.toString(filter, null),
+ "process-wide filter pattern does not match");
+ }
+
+ /**
+ * If the Global filter is already set, it should always refuse to be
+ * set again.
+ * If there is a security manager, setting the serialFilter should fail
+ * without the appropriate permission.
+ * If there is no security manager then setting it should work.
+ */
+ @Test()
+ static void setGlobalFilter() {
+ SecurityManager sm = System.getSecurityManager();
+ ObjectInputFilter filter = new SerialFilterTest.Validator();
+ ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter();
+ if (global != null) {
+ // once set, can never be re-set
+ try {
+ ObjectInputFilter.Config.setSerialFilter(filter);
+ Assert.fail("set only once process-wide filter");
+ } catch (IllegalStateException ise) {
+ if (sm != null) {
+ Assert.fail("wrong exception when security manager is set", ise);
+ }
+ } catch (SecurityException se) {
+ if (sm == null) {
+ Assert.fail("wrong exception when security manager is not set", se);
+ }
+ }
+ } else {
+ if (sm == null) {
+ // no security manager
+ try {
+ ObjectInputFilter.Config.setSerialFilter(filter);
+ // Note once set, it can not be reset; so other tests
+ System.out.printf("Global Filter set to Validator%n");
+ } catch (SecurityException se) {
+ Assert.fail("setGlobalFilter should not get SecurityException", se);
+ }
+ try {
+ // Try to set it again, expecting it to throw
+ ObjectInputFilter.Config.setSerialFilter(filter);
+ Assert.fail("set only once process-wide filter");
+ } catch (IllegalStateException ise) {
+ // Normal case
+ }
+ } else {
+ // Security manager
+ SecurityException expectSE = null;
+ try {
+ sm.checkPermission(new SerializablePermission("serialFilter"));
+ } catch (SecurityException se1) {
+ expectSE = se1;
+ }
+ SecurityException actualSE = null;
+ try {
+ ObjectInputFilter.Config.setSerialFilter(filter);
+ } catch (SecurityException se2) {
+ actualSE = se2;
+ }
+ if (expectSE == null | actualSE == null) {
+ Assert.assertEquals(expectSE, actualSE, "SecurityException");
+ } else {
+ Assert.assertEquals(expectSE.getClass(), actualSE.getClass(),
+ "SecurityException class");
+ }
+ }
+ }
+ }
+
+ /**
+ * For each pattern in the process-wide filter test a generated object
+ * against the default process-wide filter.
+ *
+ * @param pattern a pattern extracted from the configured global pattern
+ */
+ @Test(dataProvider = "globalPatternElements")
+ static void globalFilterElements(String pattern, boolean allowed,Object obj) {
+ testGlobalPattern(pattern, obj, allowed);
+ }
+
+ /**
+ * Serialize and deserialize an object using the default process-wide filter
+ * and check allowed or reject.
+ *
+ * @param pattern the pattern
+ * @param object the test object
+ * @param allowed the expected result from ObjectInputStream (exception or not)
+ */
+ static void testGlobalPattern(String pattern, Object object, boolean allowed) {
+ try {
+// System.out.printf("global %s pattern: %s, obj: %s%n", (allowed ? "allowed" : "not allowed"), pattern, object);
+ byte[] bytes = SerialFilterTest.writeObjects(object);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ Object o = ois.readObject();
+ } catch (EOFException eof) {
+ // normal completion
+ } catch (ClassNotFoundException cnf) {
+ Assert.fail("Deserializing", cnf);
+ }
+ Assert.assertTrue(allowed, "filter should have thrown an exception");
+ } catch (IllegalArgumentException iae) {
+ Assert.fail("bad format pattern", iae);
+ } catch (InvalidClassException ice) {
+ Assert.assertFalse(allowed, "filter should not have thrown an exception: " + ice);
+ } catch (IOException ioe) {
+ Assert.fail("Unexpected IOException", ioe);
+ }
+ }
+}
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/MixedFiltersTest.java b/openjdk/jdk/test/java/io/Serializable/serialFilter/MixedFiltersTest.java
new file mode 100644
index 0000000..f5aeb01
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/MixedFiltersTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Security;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/* @test
+ * @build MixedFiltersTest SerialFilterTest
+ * @run testng/othervm -Djdk.serialFilter=!java.**;!java.lang.Long;maxdepth=5;maxarray=5;maxbytes=90;maxrefs=5 MixedFiltersTest
+ * @run testng/othervm -Djdk.serialFilter=java.**;java.lang.Long;maxdepth=1000;maxarray=1000;maxbytes=1000;maxrefs=1000 MixedFiltersTest
+ *
+ * @summary Test that when both global filter and specific filter are set,
+ * global filter will not affect specific filter.
+ */
+
+public class MixedFiltersTest implements Serializable {
+
+ private static final long serialVersionUID = 1234567890L;
+
+
+ boolean globalRejected;
+
+ @BeforeClass
+ public void setup() {
+ String pattern = System.getProperty("jdk.serialFilter",
+ Security.getProperty("jdk.serialFilter"));
+ globalRejected = pattern.startsWith("!");
+ }
+
+ @DataProvider(name="RejectedInGlobal")
+ Object[][] rejectedInGlobal() {
+ if (!globalRejected) {
+ return new Object[0][];
+ }
+ return new Object[][] {
+ new Object[] { Long.MAX_VALUE, "java.**" },
+ new Object[] { Long.MAX_VALUE, "java.lang.Long" },
+ new Object[] { SerialFilterTest.genTestObject("java.lang.**", true), "java.lang.**" },
+ new Object[] { SerialFilterTest.genTestObject("maxdepth=10", true), "maxdepth=100" },
+ new Object[] { SerialFilterTest.genTestObject("maxarray=10", true), "maxarray=100" },
+ new Object[] { SerialFilterTest.genTestObject("maxbytes=100", true), "maxbytes=1000" },
+ new Object[] { SerialFilterTest.genTestObject("maxrefs=10", true), "maxrefs=100" },
+ };
+ }
+
+ /**
+ * Test:
+ * "global filter reject" + "specific ObjectInputStream filter is empty" => should reject
+ * "global filter reject" + "specific ObjectInputStream filter allow" => should allow
+ */
+ @Test(dataProvider="RejectedInGlobal")
+ public void testRejectedInGlobal(Object toDeserialized, String pattern) throws Exception {
+ byte[] bytes = SerialFilterTest.writeObjects(toDeserialized);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ Object o = ois.readObject();
+ fail("filter should have thrown an exception");
+ } catch (InvalidClassException expected) { }
+
+ ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+ Object o = ois.readObject();
+ }
+ }
+
+ @DataProvider(name="AllowedInGlobal")
+ Object[][] allowedInGlobal() {
+ if (globalRejected) {
+ return new Object[0][];
+ }
+
+ return new Object[][] {
+ new Object[] { Long.MAX_VALUE, "!java.**" },
+ new Object[] { Long.MAX_VALUE, "!java.lang.Long" },
+ new Object[] { SerialFilterTest.genTestObject("java.lang.**", true), "!java.lang.**" },
+ new Object[] { SerialFilterTest.genTestObject("maxdepth=10", true), "maxdepth=5" },
+ new Object[] { SerialFilterTest.genTestObject("maxarray=10", true), "maxarray=5" },
+ new Object[] { SerialFilterTest.genTestObject("maxbytes=100", true), "maxbytes=5" },
+ new Object[] { SerialFilterTest.genTestObject("maxrefs=10", true), "maxrefs=5" },
+ };
+ }
+
+ /**
+ * Test:
+ * "global filter allow" + "specific ObjectInputStream filter is empty" => should allow
+ * "global filter allow" + "specific ObjectInputStream filter reject" => should reject
+ */
+ @Test(dataProvider="AllowedInGlobal")
+ public void testAllowedInGlobal(Object toDeserialized, String pattern) throws Exception {
+ byte[] bytes = SerialFilterTest.writeObjects(toDeserialized);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ Object o = ois.readObject();
+ }
+
+ ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+ Object o = ois.readObject();
+ assertTrue(false, "filter should have thrown an exception");
+ } catch (InvalidClassException expected) { }
+ }
+}
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java b/openjdk/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java
new file mode 100644
index 0000000..0ab3246
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.invoke.SerializedLambda;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.concurrent.atomic.LongAdder;
+
+import sun.misc.ObjectInputFilter;
+
+import javax.lang.model.SourceVersion;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/* @test
+ * @build SerialFilterTest
+ * @run testng/othervm SerialFilterTest
+ *
+ * @summary Test ObjectInputFilters
+ */
+@Test
+public class SerialFilterTest implements Serializable {
+
+ private static final long serialVersionUID = -6999613679881262446L;
+
+ /**
+ * Enable three arg lambda.
+ * @param <T> The pattern
+ * @param <U> The test object
+ * @param <V> Boolean for if the filter should allow or reject
+ */
+ interface TriConsumer< T, U, V> {
+ void accept(T t, U u, V v);
+ }
+
+ /**
+ * Misc object to use that should always be accepted.
+ */
+ private static final Object otherObject = Integer.valueOf(0);
+
+ /**
+ * DataProvider for the individual patterns to test.
+ * Expand the patterns into cases for each of the Std and Compatibility APIs.
+ * @return an array of arrays of the parameters including factories
+ */
+ @DataProvider(name="Patterns")
+ static Object[][] patterns() {
+ Object[][] patterns = new Object[][]{
+ {"java.util.Hashtable"},
+ {"java.util.Hash*"},
+ {"javax.lang.model.*"},
+ {"javax.lang.**"},
+ {"*"},
+ {"maxarray=47"},
+ {"maxdepth=5"},
+ {"maxrefs=10"},
+ {"maxbytes=100"},
+ {"maxbytes=72"},
+ {"maxbytes=+1024"},
+ };
+ return patterns;
+ }
+
+ @DataProvider(name="InvalidPatterns")
+ static Object[][] invalidPatterns() {
+ return new Object [][] {
+ {"maxrefs=-1"},
+ {"maxdepth=-1"},
+ {"maxbytes=-1"},
+ {"maxarray=-1"},
+ {"xyz=0"},
+ {"xyz=-1"},
+ {"maxrefs=0xabc"},
+ {"maxrefs=abc"},
+ {"maxrefs="},
+ {"maxrefs=+"},
+ {".*"},
+ {".**"},
+ {"!"},
+ {"/java.util.Hashtable"},
+ {"java.base/"},
+ {"/"},
+ };
+ }
+
+ @DataProvider(name="Limits")
+ static Object[][] limits() {
+ // The numbers are arbitrary > 1
+ return new Object[][]{
+ {"maxrefs", 10},
+ {"maxdepth", 5},
+ {"maxbytes", 100},
+ {"maxarray", 16},
+ };
+ }
+
+ /**
+ * DataProvider of individual objects. Used to check the information
+ * available to the filter.
+ * @return Arrays of parameters with objects
+ */
+ @DataProvider(name="Objects")
+ static Object[][] objects() {
+ byte[] byteArray = new byte[0];
+ Object[] objArray = new Object[7];
+ objArray[objArray.length - 1] = objArray;
+
+ Class<?> serClass = null;
+ String className = "java.util.concurrent.atomic.LongAdder$SerializationProxy";
+ try {
+ serClass = Class.forName(className);
+ } catch (Exception e) {
+ Assert.fail("missing class: " + className, e);
+ }
+
+ Class<?>[] interfaces = {Runnable.class};
+ Runnable proxy = (Runnable) Proxy.newProxyInstance(null,
+ interfaces, (p, m, args) -> p);
+
+ Runnable runnable = (Runnable & Serializable) SerialFilterTest::noop;
+ Object[][] objects = {
+ { null, 0, -1, 0, 0, 0,
+ new HashSet<>()}, // no callback, no values
+ { objArray, 3, 7, 8, 2, 55,
+ new HashSet<>(Arrays.asList(objArray.getClass()))},
+ { Object[].class, 1, -1, 1, 1, 40,
+ new HashSet<>(Arrays.asList(Object[].class))},
+ { new SerialFilterTest(), 1, -1, 1, 1, 37,
+ new HashSet<>(Arrays.asList(SerialFilterTest.class))},
+ { new LongAdder(), 2, -1, 1, 1, 93,
+ new HashSet<>(Arrays.asList(LongAdder.class, serClass))},
+ { new byte[14], 2, 14, 1, 1, 27,
+ new HashSet<>(Arrays.asList(byteArray.getClass()))},
+ { runnable, 13, 0, 10, 2, 514,
+ new HashSet<>(Arrays.asList(java.lang.invoke.SerializedLambda.class,
+ SerialFilterTest.class,
+ objArray.getClass()))},
+ { deepHashSet(10), 48, -1, 49, 11, 619,
+ new HashSet<>(Arrays.asList(HashSet.class))},
+ { proxy.getClass(), 3, -1, 1, 1, 114,
+ new HashSet<>(Arrays.asList(Runnable.class,
+ java.lang.reflect.Proxy.class))},
+ };
+ return objects;
+ }
+
+ @DataProvider(name="Arrays")
+ static Object[][] arrays() {
+ return new Object[][]{
+ {new Object[16], 16},
+ {new boolean[16], 16},
+ {new byte[16], 16},
+ {new char[16], 16},
+ {new int[16], 16},
+ {new long[16], 16},
+ {new short[16], 16},
+ {new float[16], 16},
+ {new double[16], 16},
+ };
+ }
+
+
+ /**
+ * Test each object and verify the classes identified by the filter,
+ * the count of calls to the filter, the max array size, max refs, max depth,
+ * max bytes.
+ * This test ignores/is not dependent on the global filter settings.
+ *
+ * @param object a Serializable object
+ * @param count the expected count of calls to the filter
+ * @param maxArray the maximum array size
+ * @param maxRefs the maximum references
+ * @param maxDepth the maximum depth
+ * @param maxBytes the maximum stream size
+ * @param classes the expected (unique) classes
+ * @throws IOException
+ */
+ @Test(dataProvider="Objects")
+ public static void t1(Object object,
+ long count, long maxArray, long maxRefs, long maxDepth, long maxBytes,
+ Set<Class<?>> classes) throws IOException {
+ byte[] bytes = writeObjects(object);
+ Validator validator = new Validator();
+ validate(bytes, validator);
+ System.out.printf("v: %s%n", validator);
+ Assert.assertEquals(validator.count, count, "callback count wrong");
+ Assert.assertEquals(validator.classes, classes, "classes mismatch");
+ Assert.assertEquals(validator.maxArray, maxArray, "maxArray mismatch");
+ Assert.assertEquals(validator.maxRefs, maxRefs, "maxRefs wrong");
+ Assert.assertEquals(validator.maxDepth, maxDepth, "depth wrong");
+ Assert.assertEquals(validator.maxBytes, maxBytes, "maxBytes wrong");
+ }
+
+ /**
+ * Test each pattern with an appropriate object.
+ * A filter is created from the pattern and used to serialize and
+ * deserialize a generated object with both the positive and negative case.
+ * This test ignores/is not dependent on the global filter settings.
+ *
+ * @param pattern a pattern
+ */
+ @Test(dataProvider="Patterns")
+ static void testPatterns(String pattern) {
+ evalPattern(pattern, (p, o, neg) -> testPatterns(p, o, neg));
+ }
+
+ /**
+ * Test that the filter on a OIS can be set only on a fresh OIS,
+ * before deserializing any objects.
+ * This test is agnostic the global filter being set or not.
+ */
+ @Test
+ static void nonResettableFilter() {
+ Validator validator1 = new Validator();
+ Validator validator2 = new Validator();
+
+ try {
+ byte[] bytes = writeObjects("text1"); // an object
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ // Check the initial filter is the global filter; may be null
+ ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter();
+ ObjectInputFilter initial = ObjectInputFilter.Config.getObjectInputFilter(ois);
+ Assert.assertEquals(global, initial, "initial filter should be the global filter");
+
+ // Check if it can be set to null
+ ObjectInputFilter.Config.setObjectInputFilter(ois, null);
+ ObjectInputFilter filter = ObjectInputFilter.Config.getObjectInputFilter(ois);
+ Assert.assertNull(filter, "set to null should be null");
+
+ ObjectInputFilter.Config.setObjectInputFilter(ois, validator1);
+ Object o = ois.readObject();
+ try {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, validator2);
+ Assert.fail("Should not be able to set filter twice");
+ } catch (IllegalStateException ise) {
+ // success, the exception was expected
+ }
+ } catch (EOFException eof) {
+ Assert.fail("Should not reach end-of-file", eof);
+ } catch (ClassNotFoundException cnf) {
+ Assert.fail("Deserializing", cnf);
+ }
+ } catch (IOException ex) {
+ Assert.fail("Unexpected IOException", ex);
+ }
+ }
+
+ /**
+ * Test that if an Objects readReadResolve method returns an array
+ * that the callback to the filter includes the proper array length.
+ * @throws IOException if an error occurs
+ */
+ @Test(dataProvider="Arrays")
+ static void testReadResolveToArray(Object array, int length) throws IOException {
+ ReadResolveToArray object = new ReadResolveToArray(array, length);
+ byte[] bytes = writeObjects(object);
+ Object o = validate(bytes, object); // the object is its own filter
+ Assert.assertEquals(o.getClass(), array.getClass(), "Filter not called with the array");
+ }
+
+ /**
+ * Test repeated limits use the last value.
+ * Construct a filter with the limit and the limit repeated -1.
+ * Invoke the filter with the limit to make sure it is rejected.
+ * Invoke the filter with the limit -1 to make sure it is accepted.
+ * @param name the name of the limit to test
+ * @param value a test value
+ */
+ @Test(dataProvider="Limits")
+ static void testLimits(String name, int value) {
+ Class<?> arrayClass = new int[0].getClass();
+ String pattern = String.format("%s=%d;%s=%d", name, value, name, value - 1);
+ ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+ Assert.assertEquals(
+ filter.checkInput(new FilterValues(arrayClass, value, value, value, value)),
+ ObjectInputFilter.Status.REJECTED,
+ "last limit value not used: " + filter);
+ Assert.assertEquals(
+ filter.checkInput(new FilterValues(arrayClass, value-1, value-1, value-1, value-1)),
+ ObjectInputFilter.Status.UNDECIDED,
+ "last limit value not used: " + filter);
+ }
+
+ /**
+ * Test that returning null from a filter causes deserialization to fail.
+ */
+ @Test(expectedExceptions=InvalidClassException.class)
+ static void testNullStatus() throws IOException {
+ byte[] bytes = writeObjects(0); // an Integer
+ try {
+ Object o = validate(bytes, new ObjectInputFilter() {
+ public ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo f) {
+ return null;
+ }
+ });
+ } catch (InvalidClassException ice) {
+ System.out.printf("Success exception: %s%n", ice);
+ throw ice;
+ }
+ }
+
+ /**
+ * Verify that malformed patterns throw IAE.
+ * @param pattern pattern from the data source
+ */
+ @Test(dataProvider="InvalidPatterns", expectedExceptions=IllegalArgumentException.class)
+ static void testInvalidPatterns(String pattern) {
+ try {
+ ObjectInputFilter.Config.createFilter(pattern);
+ } catch (IllegalArgumentException iae) {
+ System.out.printf(" success exception: %s%n", iae);
+ throw iae;
+ }
+ }
+
+ /**
+ * Test that Config.create returns null if the argument does not contain any patterns or limits.
+ */
+ @Test()
+ static void testEmptyPattern() {
+ ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("");
+ Assert.assertNull(filter, "empty pattern did not return null");
+
+ filter = ObjectInputFilter.Config.createFilter(";;;;");
+ Assert.assertNull(filter, "pattern with only delimiters did not return null");
+ }
+
+ /**
+ * Read objects from the serialized stream, validated with the filter.
+ *
+ * @param bytes a byte array to read objects from
+ * @param filter the ObjectInputFilter
+ * @return the object deserialized if any
+ * @throws IOException can be thrown
+ */
+ static Object validate(byte[] bytes,
+ ObjectInputFilter filter) throws IOException {
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+
+ Object o = ois.readObject();
+ return o;
+ } catch (EOFException eof) {
+ // normal completion
+ } catch (ClassNotFoundException cnf) {
+ Assert.fail("Deserializing", cnf);
+ }
+ return null;
+ }
+
+ /**
+ * Write objects and return a byte array with the bytes.
+ *
+ * @param objects zero or more objects to serialize
+ * @return the byte array of the serialized objects
+ * @throws IOException if an exception occurs
+ */
+ static byte[] writeObjects(Object... objects) throws IOException {
+ byte[] bytes;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ for (Object o : objects) {
+ oos.writeObject(o);
+ }
+ bytes = baos.toByteArray();
+ }
+ return bytes;
+ }
+
+ /**
+ * A filter that accumulates information about the checkInput callbacks
+ * that can be checked after readObject completes.
+ */
+ static class Validator implements ObjectInputFilter {
+ long count; // Count of calls to checkInput
+ HashSet<Class<?>> classes = new HashSet<>();
+ long maxArray = -1;
+ long maxRefs;
+ long maxDepth;
+ long maxBytes;
+
+ Validator() {
+ }
+
+ @Override
+ public ObjectInputFilter.Status checkInput(FilterInfo filter) {
+ count++;
+ if (filter.serialClass() != null) {
+ if (filter.serialClass().getName().contains("$$Lambda$")) {
+ // TBD: proper identification of serialized Lambdas?
+ // Fold the serialized Lambda into the SerializedLambda type
+ classes.add(SerializedLambda.class);
+ } else if (Proxy.isProxyClass(filter.serialClass())) {
+ classes.add(Proxy.class);
+ } else {
+ classes.add(filter.serialClass());
+ }
+
+ }
+ this.maxArray = Math.max(this.maxArray, filter.arrayLength());
+ this.maxRefs = Math.max(this.maxRefs, filter.references());
+ this.maxDepth = Math.max(this.maxDepth, filter.depth());
+ this.maxBytes = Math.max(this.maxBytes, filter.streamBytes());
+ return ObjectInputFilter.Status.UNDECIDED;
+ }
+
+ public String toString(){
+ return "count: " + count
+ + ", classes: " + classes.toString()
+ + ", maxArray: " + maxArray
+ + ", maxRefs: " + maxRefs
+ + ", maxDepth: " + maxDepth
+ + ", maxBytes: " + maxBytes;
+ }
+ }
+
+
+ /**
+ * Create a filter from a pattern and API factory, then serialize and
+ * deserialize an object and check allowed or reject.
+ *
+ * @param pattern the pattern
+ * @param object the test object
+ * @param allowed the expected result from ObjectInputStream (exception or not)
+ */
+ static void testPatterns(String pattern, Object object, boolean allowed) {
+ try {
+ byte[] bytes = SerialFilterTest.writeObjects(object);
+ ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+ validate(bytes, filter);
+ Assert.assertTrue(allowed, "filter should have thrown an exception");
+ } catch (IllegalArgumentException iae) {
+ Assert.fail("bad format pattern", iae);
+ } catch (InvalidClassException ice) {
+ Assert.assertFalse(allowed, "filter should not have thrown an exception: " + ice);
+ } catch (IOException ioe) {
+ Assert.fail("Unexpected IOException", ioe);
+ }
+ }
+
+ /**
+ * For a filter pattern, generate and apply a test object to the action.
+ * @param pattern a pattern
+ * @param action an action to perform on positive and negative cases
+ */
+ static void evalPattern(String pattern, TriConsumer<String, Object, Boolean> action) {
+ Object o = genTestObject(pattern, true);
+ Assert.assertNotNull(o, "success generation failed");
+ action.accept(pattern, o, true);
+
+ // Test the negative pattern
+ o = genTestObject(pattern, false);
+ Assert.assertNotNull(o, "fail generation failed");
+ String negPattern = pattern.contains("=") ? pattern : "!" + pattern;
+ action.accept(negPattern, o, false);
+ }
+
+ /**
+ * Generate a test object based on the pattern.
+ * Handles each of the forms of the pattern, wildcards,
+ * class name, various limit forms.
+ * @param pattern a pattern
+ * @param allowed a boolean indicating to generate the allowed or disallowed case
+ * @return an object or {@code null} to indicate no suitable object could be generated
+ */
+ static Object genTestObject(String pattern, boolean allowed) {
+ if (pattern.contains("=")) {
+ return genTestLimit(pattern, allowed);
+ } else if (pattern.endsWith("*")) {
+ return genTestObjectWildcard(pattern, allowed);
+ } else {
+ // class
+ try {
+ Class<?> clazz = Class.forName(pattern);
+ Constructor<?> cons = clazz.getConstructor();
+ return cons.newInstance();
+ } catch (ClassNotFoundException ex) {
+ Assert.fail("no such class available: " + pattern);
+ } catch (InvocationTargetException
+ | NoSuchMethodException
+ | InstantiationException
+ | IllegalAccessException ex1) {
+ Assert.fail("newInstance: " + ex1);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Generate an object to be used with the various wildcard pattern forms.
+ * Explicitly supports only specific package wildcards with specific objects.
+ * @param pattern a wildcard pattern ending in "*"
+ * @param allowed a boolean indicating to generate the allowed or disallowed case
+ * @return an object within or outside the wildcard
+ */
+ static Object genTestObjectWildcard(String pattern, boolean allowed) {
+ if (pattern.endsWith(".**")) {
+ // package hierarchy wildcard
+ if (pattern.startsWith("javax.lang.")) {
+ return SourceVersion.RELEASE_5;
+ }
+ if (pattern.startsWith("java.")) {
+ return 4;
+ }
+ if (pattern.startsWith("javax.")) {
+ return SourceVersion.RELEASE_6;
+ }
+ return otherObject;
+ } else if (pattern.endsWith(".*")) {
+ // package wildcard
+ if (pattern.startsWith("javax.lang.model")) {
+ return SourceVersion.RELEASE_6;
+ }
+ } else {
+ // class wildcard
+ if (pattern.equals("*")) {
+ return otherObject; // any object will do
+ }
+ if (pattern.startsWith("java.util.Hash")) {
+ return new Hashtable<String, String>();
+ }
+ }
+ Assert.fail("Object could not be generated for pattern: "
+ + pattern
+ + ", allowed: " + allowed);
+ return null;
+ }
+
+ /**
+ * Generate a limit test object for the pattern.
+ * For positive cases, the object exactly hits the limit.
+ * For negative cases, the object is 1 greater than the limit
+ * @param pattern the pattern, containing "=" and a maxXXX keyword
+ * @param allowed a boolean indicating to generate the allowed or disallowed case
+ * @return a sitable object
+ */
+ static Object genTestLimit(String pattern, boolean allowed) {
+ int ndx = pattern.indexOf('=');
+ Assert.assertNotEquals(ndx, -1, "missing value in limit");
+ long value = Long.parseUnsignedLong(pattern.substring(ndx+1));
+ if (pattern.startsWith("maxdepth=")) {
+ // Return an object with the requested depth (or 1 greater)
+ long depth = allowed ? value : value + 1;
+ Object[] array = new Object[1];
+ for (int i = 1; i < depth; i++) {
+ Object[] n = new Object[1];
+ n[0] = array;
+ array = n;
+ }
+ return array;
+ } else if (pattern.startsWith("maxbytes=")) {
+ // Return a byte array that when written to OOS creates
+ // a stream of exactly the size requested.
+ return genMaxBytesObject(allowed, value);
+ } else if (pattern.startsWith("maxrefs=")) {
+ Object[] array = new Object[allowed ? (int)value - 1 : (int)value];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = otherObject;
+ }
+ return array;
+ } else if (pattern.startsWith("maxarray=")) {
+ return allowed ? new int[(int)value] : new int[(int)value+1];
+ }
+ Assert.fail("Object could not be generated for pattern: "
+ + pattern
+ + ", allowed: " + allowed);
+ return null;
+ }
+
+ /**
+ * Generate an an object that will be serialized to some number of bytes.
+ * Or 1 greater if allowed is false.
+ * It returns a two element Object array holding a byte array sized
+ * to achieve the desired total size.
+ * @param allowed true if the stream should be allowed at that size,
+ * false if the stream should be larger
+ * @param maxBytes the number of bytes desired in the stream;
+ * should not be less than 72 (due to protocol overhead).
+ * @return a object that will be serialized to the length requested
+ */
+ private static Object genMaxBytesObject(boolean allowed, long maxBytes) {
+ Object[] holder = new Object[2];
+ long desiredSize = allowed ? maxBytes : maxBytes + 1;
+ long actualSize = desiredSize;
+ long byteSize = desiredSize - 72; // estimate needed array size
+ do {
+ byteSize += (desiredSize - actualSize);
+ byte[] a = new byte[(int)byteSize];
+ holder[0] = a;
+ holder[1] = a;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(baos)) {
+ os.writeObject(holder);
+ os.flush();
+ actualSize = baos.size();
+ } catch (IOException ie) {
+ Assert.fail("exception generating stream", ie);
+ }
+ } while (actualSize != desiredSize);
+ return holder;
+ }
+
+ /**
+ * Returns a HashSet of a requested depth.
+ * @param depth the depth
+ * @return a HashSet of HashSets...
+ */
+ static HashSet<Object> deepHashSet(int depth) {
+ HashSet<Object> hashSet = new HashSet<>();
+ HashSet<Object> s1 = hashSet;
+ HashSet<Object> s2 = new HashSet<>();
+ for (int i = 0; i < depth; i++ ) {
+ HashSet<Object> t1 = new HashSet<>();
+ HashSet<Object> t2 = new HashSet<>();
+ // make t1 not equal to t2
+ t1.add("by Jimminy");
+ s1.add(t1);
+ s1.add(t2);
+ s2.add(t1);
+ s2.add(t2);
+ s1 = t1;
+ s2 = t2;
+ }
+ return hashSet;
+ }
+
+ /**
+ * Simple method to use with Serialized Lambda.
+ */
+ private static void noop() {}
+
+
+ /**
+ * Class that returns an array from readResolve and also implements
+ * the ObjectInputFilter to check that it has the expected length.
+ */
+ static class ReadResolveToArray implements Serializable, ObjectInputFilter {
+ private static final long serialVersionUID = 123456789L;
+
+ private final Object array;
+ private final int length;
+
+ ReadResolveToArray(Object array, int length) {
+ this.array = array;
+ this.length = length;
+ }
+
+ Object readResolve() {
+ return array;
+ }
+
+ @Override
+ public ObjectInputFilter.Status checkInput(FilterInfo filter) {
+ if (ReadResolveToArray.class.isAssignableFrom(filter.serialClass())) {
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ if (filter.serialClass() != array.getClass() ||
+ (filter.arrayLength() >= 0 && filter.arrayLength() != length)) {
+ return ObjectInputFilter.Status.REJECTED;
+ }
+ return ObjectInputFilter.Status.UNDECIDED;
+ }
+
+ }
+
+ /**
+ * Hold a snapshot of values to be passed to an ObjectInputFilter.
+ */
+ static class FilterValues implements ObjectInputFilter.FilterInfo {
+ private final Class<?> clazz;
+ private final long arrayLength;
+ private final long depth;
+ private final long references;
+ private final long streamBytes;
+
+ public FilterValues(Class<?> clazz, long arrayLength, long depth, long references, long streamBytes) {
+ this.clazz = clazz;
+ this.arrayLength = arrayLength;
+ this.depth = depth;
+ this.references = references;
+ this.streamBytes = streamBytes;
+ }
+
+ @Override
+ public Class<?> serialClass() {
+ return clazz;
+ }
+
+ public long arrayLength() {
+ return arrayLength;
+ }
+
+ public long depth() {
+ return depth;
+ }
+
+ public long references() {
+ return references;
+ }
+
+ public long streamBytes() {
+ return streamBytes;
+ }
+ }
+}
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/java.security-extra1 b/openjdk/jdk/test/java/io/Serializable/serialFilter/java.security-extra1
new file mode 100644
index 0000000..7a52040
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/java.security-extra1
@@ -0,0 +1,4 @@
+# Serialization Input Process-wide Filter
+# See conf/security/java.security for pattern synatx
+#
+jdk.serialFilter=java.**;javax.**;maxarray=34;maxdepth=7
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/security.policy b/openjdk/jdk/test/java/io/Serializable/serialFilter/security.policy
new file mode 100644
index 0000000..f986e25
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/security.policy
@@ -0,0 +1,17 @@
+// Individual Permissions to for GlobalFilterTest
+grant {
+ // Specific permission under test
+ permission java.security.SerializablePermission "serialFilter";
+ // Permissions needed to run the test
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.security.SecurityPermission "*";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+};
+
+// Standard extensions get all permissions by default
+grant codeBase "file:${{java.ext.dirs}}/*" {
+ permission java.security.AllPermission;
+};
diff --git a/openjdk/jdk/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter b/openjdk/jdk/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter
new file mode 100644
index 0000000..2f80b82
--- /dev/null
+++ openjdk/jdk/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter
@@ -0,0 +1,15 @@
+// Individual Permissions for FilterWithSecurityManagerTest
+grant {
+ // Permissions needed to run the test
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+};
+
+// Standard extensions get all permissions by default
+grant codeBase "file:${{java.ext.dirs}}/*" {
+ permission java.security.AllPermission;
+};
+
diff --git a/openjdk/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java b/openjdk/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java
new file mode 100644
index 0000000..ae9f8e3
--- /dev/null
+++ openjdk/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+import java.util.Objects;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/* @test
+ * @run testng/othervm MOFilterTest
+ *
+ * @summary Test MarshalledObject applies ObjectInputFilter
+ */
+@Test
+public class MOFilterTest {
+
+ /**
+ * Two cases are tested.
+ * The filter = null and a filter set to verify the calls to the filter.
+ * @return array objects with test parameters for each test case
+ */
+ @DataProvider(name = "FilterCases")
+ public static Object[][] filterCases() {
+ return new Object[][] {
+ {true}, // run the test with the filter
+ {false}, // run the test without the filter
+
+ };
+ }
+
+ /**
+ * Test that MarshalledObject inherits the ObjectInputFilter from
+ * the stream it was deserialized from.
+ */
+ @Test(dataProvider="FilterCases")
+ static void delegatesToMO(boolean withFilter) {
+ try {
+ Serializable testobj = Integer.valueOf(5);
+ MarshalledObject<Serializable> mo = new MarshalledObject<>(testobj);
+ Assert.assertEquals(mo.get(), testobj, "MarshalledObject.get returned a non-equals test object");
+
+ byte[] bytes = writeObjects(mo);
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+
+ CountingFilter filter1 = new CountingFilter();
+ ObjectInputFilter.Config.setObjectInputFilter(ois, withFilter ? filter1 : null);
+ MarshalledObject<?> actualMO = (MarshalledObject<?>)ois.readObject();
+ int count = filter1.getCount();
+
+ actualMO.get();
+ int expectedCount = withFilter ? count + 2 : count;
+ int actualCount = filter1.getCount();
+ Assert.assertEquals(actualCount, expectedCount, "filter called wrong number of times during get()");
+ }
+ } catch (IOException ioe) {
+ Assert.fail("Unexpected IOException", ioe);
+ } catch (ClassNotFoundException cnf) {
+ Assert.fail("Deserializing", cnf);
+ }
+ }
+
+ /**
+ * Write objects and return a byte array with the bytes.
+ *
+ * @param objects zero or more objects to serialize
+ * @return the byte array of the serialized objects
+ * @throws IOException if an exception occurs
+ */
+ static byte[] writeObjects(Object... objects) throws IOException {
+ byte[] bytes;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ for (Object o : objects) {
+ oos.writeObject(o);
+ }
+ bytes = baos.toByteArray();
+ }
+ return bytes;
+ }
+
+
+ static class CountingFilter implements ObjectInputFilter {
+
+ private int count; // count of calls to the filter
+
+ CountingFilter() {
+ count = 0;
+ }
+
+ int getCount() {
+ return count;
+ }
+
+ /**
+ * Filter that rejects class Integer and allows others
+ *
+ * @param filterInfo access to the class, arrayLength, etc.
+ * @return {@code STATUS.REJECTED}
+ */
+ public ObjectInputFilter.Status checkInput(FilterInfo filterInfo) {
+ count++;
+ return ObjectInputFilter.Status.ALLOWED;
+ }
+ }
+
+}
diff --git a/openjdk/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java b/openjdk/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java
new file mode 100644
index 0000000..e29e24a
--- /dev/null
+++ openjdk/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.rmi.MarshalledObject;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Objects;
+import java.security.Security;
+
+import org.testng.Assert;
+import org.testng.TestNG;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @library /java/rmi/testlibrary
+ * @modules java.rmi/sun.rmi.registry
+ * java.rmi/sun.rmi.server
+ * java.rmi/sun.rmi.transport
+ * java.rmi/sun.rmi.transport.tcp
+ * @build TestLibrary
+ * @summary Test filters for the RMI Registry
+ * @run testng/othervm RegistryFilterTest
+ * @run testng/othervm
+ * -Dsun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass
+ * RegistryFilterTest
+ * @run testng/othervm/policy=security.policy
+ * -Djava.security.properties=${test.src}/java.security-extra1
+ * RegistryFilterTest
+ */
+public class RegistryFilterTest {
+ private static Registry impl;
+ private static int port;
+ private static Registry registry;
+
+ static final int REGISTRY_MAX_ARRAY = 10000;
+
+ static final String registryFilter =
+ System.getProperty("sun.rmi.registry.registryFilter",
+ Security.getProperty("sun.rmi.registry.registryFilter"));
+
+ @DataProvider(name = "bindAllowed")
+ static Object[][] bindAllowedObjects() {
+ Object[][] objects = {
+ };
+ return objects;
+ }
+
+ /**
+ * Data RMI Regiry bind test.
+ * - name
+ * - Object
+ * - true/false if object is blacklisted by a filter (implicit or explicit)
+ * @return array of test data
+ */
+ @DataProvider(name = "bindData")
+ static Object[][] bindObjects() {
+ Object[][] data = {
+ { "byte[max]", new XX(new byte[REGISTRY_MAX_ARRAY]), false },
+ { "String", new XX("now is the time"), false},
+ { "String[]", new XX(new String[3]), false},
+ { "Long[4]", new XX(new Long[4]), registryFilter != null },
+ { "rej-byte[toobig]", new XX(new byte[REGISTRY_MAX_ARRAY + 1]), true },
+ { "rej-MarshalledObject", createMarshalledObject(), true },
+ { "rej-RejectableClass", new RejectableClass(), registryFilter != null},
+ };
+ return data;
+ }
+
+ static XX createMarshalledObject() {
+ try {
+ return new XX(new MarshalledObject<>(null));
+ } catch (IOException ioe) {
+ return new XX(ioe);
+ }
+ }
+
+ @BeforeSuite
+ static void setupRegistry() {
+ try {
+ impl = TestLibrary.createRegistryOnEphemeralPort();
+ port = TestLibrary.getRegistryPort(impl);
+ registry = LocateRegistry.getRegistry("localhost", port);
+ } catch (RemoteException ex) {
+ Assert.fail("initialization of registry", ex);
+ }
+
+ System.out.printf("RMI Registry filter: %s%n", registryFilter);
+ }
+
+
+ /*
+ * Test registry rejects an object with the max array size + 1.
+ */
+ @Test(dataProvider="bindData")
+ public void simpleBind(String name, Remote obj, boolean blacklisted) throws RemoteException, AlreadyBoundException, NotBoundException {
+ try {
+ registry.bind(name, obj);
+ Assert.assertFalse(blacklisted, "Registry filter did not reject (but should have) ");
+ registry.unbind(name);
+ } catch (Exception rex) {
+ Assert.assertTrue(blacklisted, "Registry filter should not have rejected");
+ }
+ }
+
+ /*
+ * Test registry rejects an object with a well known class
+ * if blacklisted in the security properties.
+ */
+ @Test
+ public void simpleRejectableClass() throws RemoteException, AlreadyBoundException, NotBoundException {
+ RejectableClass r1 = null;
+ try {
+ String name = "reject1";
+ r1 = new RejectableClass();
+ registry.bind(name, r1);
+ registry.unbind(name);
+ Assert.assertNull(registryFilter, "Registry filter should not have rejected");
+ } catch (Exception rex) {
+ Assert.assertNotNull(registryFilter, "Registry filter should have rejected");
+ }
+ }
+
+ /**
+ * A simple Serializable Remote object that is passed by value.
+ * It and its contents are checked by the Registry serial filter.
+ */
+ static class XX implements Serializable, Remote {
+ private static final long serialVersionUID = 362498820763181265L;
+
+ final Object obj;
+
+ XX(Object obj) {
+ this.obj = obj;
+ }
+
+ public String toString() {
+ return super.toString() + "//" + Objects.toString(obj);
+ }
+ }
+ /**
+ * A simple Serializable Remote object that is passed by value.
+ * It and its contents are checked by the Registry serial filter.
+ */
+ static class RejectableClass implements Serializable, Remote {
+ private static final long serialVersionUID = 362498820763181264L;
+
+ RejectableClass() {}
+ }
+
+}
diff --git a/openjdk/jdk/test/java/rmi/registry/serialFilter/java.security-extra1 b/openjdk/jdk/test/java/rmi/registry/serialFilter/java.security-extra1
new file mode 100644
index 0000000..2629e99
--- /dev/null
+++ openjdk/jdk/test/java/rmi/registry/serialFilter/java.security-extra1
@@ -0,0 +1,8 @@
+# RMI Registry Input Serial Filter
+#
+# The filter pattern uses the same format as java.io.ObjectInputStream.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+sun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass
+
diff --git a/openjdk/jdk/test/java/rmi/registry/serialFilter/security.policy b/openjdk/jdk/test/java/rmi/registry/serialFilter/security.policy
new file mode 100644
index 0000000..554e9ea
--- /dev/null
+++ openjdk/jdk/test/java/rmi/registry/serialFilter/security.policy
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+
diff --git a/openjdk/jdk/test/java/security/Signature/SignatureLength.java b/openjdk/jdk/test/java/security/Signature/SignatureLength.java
new file mode 100644
index 0000000..13c4a6d
--- /dev/null
+++ openjdk/jdk/test/java/security/Signature/SignatureLength.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.*;
+
+/*
+ * @test
+ * @bug 8161571
+ * @summary Reject signatures presented for verification that contain extra
+ * bytes.
+ * @run main SignatureLength
+ */
+public class SignatureLength {
+
+ public static void main(String[] args) throws Exception {
+ main0("EC", 256, "SHA256withECDSA", "SunEC");
+ main0("RSA", 2048, "SHA256withRSA", "SunRsaSign");
+ main0("DSA", 2048, "SHA256withDSA", "SUN");
+
+ if (System.getProperty("os.name").equals("SunOS")) {
+ main0("EC", 256, "SHA256withECDSA", null);
+ main0("RSA", 2048, "SHA256withRSA", null);
+ }
+ }
+
+ private static void main0(String keyAlgorithm, int keysize,
+ String signatureAlgorithm, String provider) throws Exception {
+ byte[] plaintext = "aaa".getBytes("UTF-8");
+
+ // Generate
+ KeyPairGenerator generator =
+ provider == null ?
+ (KeyPairGenerator) KeyPairGenerator.getInstance(keyAlgorithm) :
+ (KeyPairGenerator) KeyPairGenerator.getInstance(
+ keyAlgorithm, provider);
+ generator.initialize(keysize);
+ System.out.println("Generating " + keyAlgorithm + " keypair using " +
+ generator.getProvider().getName() + " JCE provider");
+ KeyPair keypair = generator.generateKeyPair();
+
+ // Sign
+ Signature signer =
+ provider == null ?
+ Signature.getInstance(signatureAlgorithm) :
+ Signature.getInstance(signatureAlgorithm, provider);
+ signer.initSign(keypair.getPrivate());
+ signer.update(plaintext);
+ System.out.println("Signing using " + signer.getProvider().getName() +
+ " JCE provider");
+ byte[] signature = signer.sign();
+
+ // Invalidate
+ System.out.println("Invalidating signature ...");
+ byte[] badSignature = new byte[signature.length + 5];
+ System.arraycopy(signature, 0, badSignature, 0, signature.length);
+ badSignature[signature.length] = 0x01;
+ badSignature[signature.length + 1] = 0x01;
+ badSignature[signature.length + 2] = 0x01;
+ badSignature[signature.length + 3] = 0x01;
+ badSignature[signature.length + 4] = 0x01;
+
+ // Verify
+ Signature verifier =
+ provider == null ?
+ Signature.getInstance(signatureAlgorithm) :
+ Signature.getInstance(signatureAlgorithm, provider);
+ verifier.initVerify(keypair.getPublic());
+ verifier.update(plaintext);
+ System.out.println("Verifying using " +
+ verifier.getProvider().getName() + " JCE provider");
+
+ try {
+ System.out.println("Valid? " + verifier.verify(badSignature));
+ throw new Exception(
+ "ERROR: expected a SignatureException but none was thrown");
+ } catch (SignatureException e) {
+ System.out.println("OK: caught expected exception: " + e);
+ }
+ System.out.println();
+ }
+}
diff --git a/openjdk/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/openjdk/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
index 7808624..9484e38 100644
--- openjdk/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
+++ openjdk/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
@@ -49,7 +49,7 @@ import org.testng.annotations.Test;
/*
* @test
- * @bug 8081022 8151876
+ * @bug 8081022 8151876 8166875
* @key randomness
*/
diff --git a/openjdk/jdk/test/java/time/test/java/time/format/ZoneName.java b/openjdk/jdk/test/java/time/test/java/time/format/ZoneName.java
index 2c49446..1fbb913 100644
--- openjdk/jdk/test/java/time/test/java/time/format/ZoneName.java
+++ openjdk/jdk/test/java/time/test/java/time/format/ZoneName.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -378,6 +378,7 @@ class ZoneName {
"Europe/Helsinki", "Europe_Eastern", "Europe/Bucharest",
"America/Nome", "Alaska", "America/Juneau",
"Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk",
+ "Asia/Yangon", "Myanmar", "Asia/Rangoon",
"Africa/Conakry", "GMT", "Atlantic/Reykjavik",
"Asia/Seoul", "Korea", "Asia/Seoul",
"America/Antigua", "Atlantic", "America/Halifax",
@@ -747,6 +748,7 @@ class ZoneName {
"NZ", "Pacific/Auckland",
"Asia/Tel_Aviv", "Asia/Jerusalem",
"Hongkong", "Asia/Hong_Kong",
+ "Asia/Rangoon", "Asia/Yangon",
};
private static final Map<String, String> zidToMzone = new HashMap<>();
diff --git a/openjdk/jdk/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java b/openjdk/jdk/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java
new file mode 100644
index 0000000..4532e83
--- /dev/null
+++ openjdk/jdk/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8139565
+ * @summary Restrict certificates with DSA keys less than 1024 bits
+ *
+ * @run main/othervm DisabledShortDSAKeys PKIX TLSv1.2
+ * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.2
+ * @run main/othervm DisabledShortDSAKeys PKIX TLSv1.1
+ * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.1
+ * @run main/othervm DisabledShortDSAKeys PKIX TLSv1
+ * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1
+ * @run main/othervm DisabledShortDSAKeys PKIX SSLv3
+ * @run main/othervm DisabledShortDSAKeys SunX509 SSLv3
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.Security;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.util.Base64;
+
+
+public class DisabledShortDSAKeys {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ // Certificates and key used in the test.
+ static String trustedCertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDDjCCAs2gAwIBAgIJAO5/hbm1ByJOMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" +
+ "VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzcwMTI2MDQz\n" +
+ "NTQ2WjAfMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXhhbXBsZTCCAbgwggEsBgcq\n" +
+ "hkjOOAQBMIIBHwKBgQC4aSK8nBYdWJtuBkz6yoDyjZnNuGFSpDmx1ggKpLpcnPuw\n" +
+ "YKAbUhqdYhZtaIqQ4aO0T1ZS/HuOM0zvddnMUidFNX3RUvDkvdD/JYOnjqzCm+xW\n" +
+ "U0NFuPHZdapQY5KFk3ugkqZpHLY1StZbu0qugZOZjbBOMwB7cHAbMDuVpEr8DQIV\n" +
+ "AOi+ig+h3okFbWEE9MztiI2+DqNrAoGBAKh2EZbuWU9NoHglhVzfDUoz8CeyW6W6\n" +
+ "rUZuIOQsjWaYOeRPWX0UVAGq9ykIOfamEpurKt4H8ge/pHaL9iazJjonMHOXG12A\n" +
+ "0lALsMDGv22zVaJzXjOBvdPzc87opr0LIVgHASKOcDYjsICKNYPlS2cL3MJoD+bj\n" +
+ "NAR67b90VBbEA4GFAAKBgQCGrkRp2tdj2mZF7Qz0tO6p3xSysbEfN6QZxOJYPTvM\n" +
+ "yIYfLV9Yoy7XaRd/mCpJo/dqmsZMzowtyi+u+enuVpOLKiq/lyCktL+xUzZAjLT+\n" +
+ "9dafHlS1wR3pDSa1spo9xTEi4Ff/DQDHcdGalBxSXX/UdRtSecIYAp5/fkt3QZ5v\n" +
+ "0aOBkTCBjjAdBgNVHQ4EFgQUX4qbP5PgBx1J8BJ8qEgfoKVLSnQwTwYDVR0jBEgw\n" +
+ "RoAUX4qbP5PgBx1J8BJ8qEgfoKVLSnShI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+ "VQQKEwdFeGFtcGxlggkA7n+FubUHIk4wDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8E\n" +
+ "BAMCAgQwCQYHKoZIzjgEAwMwADAtAhUAkr5bINXyy/McAx6qwhb6r0/QJUgCFFUP\n" +
+ "CZokA4/NqJIgq8ThpTQAE8SB\n" +
+ "-----END CERTIFICATE-----";
+
+ static String targetCertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIICUjCCAhGgAwIBAgIJAIiDrs/4W8rtMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" +
+ "VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzUxMTAzMDQz\n" +
+ "NTQ2WjA5MQswCQYDVQQGEwJVUzEQMA4GA1UECgwHRXhhbXBsZTEYMBYGA1UEAwwP\n" +
+ "d3d3LmV4YW1wbGUuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSv\n" +
+ "ThR/8GHpbL49KyWRJBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmp\n" +
+ "zYlUywIVAJLDcf4JXhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk\n" +
+ "5B8+ZHaHRi2KQ00ejilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14A0MA\n" +
+ "AkAYb+DYlFgStFhF1ip7rFzY8K6i/3ellkXI2umI/XVwxUQTHSlk5nFOep5Dfzm9\n" +
+ "pADJwuSe1qGHsHB5LpMZPVpto4GEMIGBMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgPo\n" +
+ "MB0GA1UdDgQWBBT8nsFyccF4q1dtpWE1dkNK5UiXtTAfBgNVHSMEGDAWgBRfips/\n" +
+ "k+AHHUnwEnyoSB+gpUtKdDAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
+ "CCsGAQUFBwMDMAkGByqGSM44BAMDMAAwLQIUIcIlxpIwaZXdpMC+U076unR1Mp8C\n" +
+ "FQCD/NE8O0xwq57nwFfp7tUvUHYMMA==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Private key in the format of PKCS#8, key size is 512 bits.
+ static String targetPrivateKey =
+ "MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSvThR/8GHpbL49KyWR\n" +
+ "JBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmpzYlUywIVAJLDcf4J\n" +
+ "XhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk5B8+ZHaHRi2KQ00e\n" +
+ "jilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14BBYCFHB2Wek2g5hpNj5y\n" +
+ "RQfCc6CFO0dv";
+
+ static char passphrase[] = "passphrase".toCharArray();
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLContext context = generateSSLContext(null, targetCertStr,
+ targetPrivateKey);
+ SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket)sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
+ try (InputStream sslIS = sslSocket.getInputStream()) {
+ sslIS.read();
+ }
+
+ throw new Exception(
+ "DSA keys shorter than 1024 bits should be disabled");
+ } catch (SSLHandshakeException sslhe) {
+ // the expected exception, ignore
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLContext context = generateSSLContext(trustedCertStr, null, null);
+ SSLSocketFactory sslsf = context.getSocketFactory();
+
+ try (SSLSocket sslSocket =
+ (SSLSocket)sslsf.createSocket("localhost", serverPort)) {
+
+ // only enable the target protocol
+ sslSocket.setEnabledProtocols(new String[] {enabledProtocol});
+
+ // enable a block cipher
+ sslSocket.setEnabledCipherSuites(
+ new String[] {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA"});
+
+ try (OutputStream sslOS = sslSocket.getOutputStream()) {
+ sslOS.write('B');
+ sslOS.flush();
+ }
+
+ throw new Exception(
+ "DSA keys shorter than 1024 bits should be disabled");
+ } catch (SSLHandshakeException sslhe) {
+ // the expected exception, ignore
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+ private static String tmAlgorithm; // trust manager
+ private static String enabledProtocol; // the target protocol
+
+ private static void parseArguments(String[] args) {
+ tmAlgorithm = args[0];
+ enabledProtocol = args[1];
+ }
+
+ private static SSLContext generateSSLContext(String trustedCertStr,
+ String keyCertStr, String keySpecStr) throws Exception {
+
+ // generate certificate from cert string
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ // create a key store
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+
+ // import the trused cert
+ Certificate trusedCert = null;
+ ByteArrayInputStream is = null;
+ if (trustedCertStr != null) {
+ is = new ByteArrayInputStream(trustedCertStr.getBytes());
+ trusedCert = cf.generateCertificate(is);
+ is.close();
+
+ ks.setCertificateEntry("DSA Export Signer", trusedCert);
+ }
+
+ if (keyCertStr != null) {
+ // generate the private key.
+ PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+ Base64.getMimeDecoder().decode(keySpecStr));
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+ DSAPrivateKey priKey =
+ (DSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+ // generate certificate chain
+ is = new ByteArrayInputStream(keyCertStr.getBytes());
+ Certificate keyCert = cf.generateCertificate(is);
+ is.close();
+
+ Certificate[] chain = null;
+ if (trusedCert != null) {
+ chain = new Certificate[2];
+ chain[0] = keyCert;
+ chain[1] = trusedCert;
+ } else {
+ chain = new Certificate[1];
+ chain[0] = keyCert;
+ }
+
+ // import the key entry.
+ ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+ }
+
+ // create SSL context
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+ tmf.init(ks);
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ if (keyCertStr != null && !keyCertStr.isEmpty()) {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+ kmf.init(ks, passphrase);
+
+ ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ ks = null;
+ } else {
+ ctx.init(null, tmf.getTrustManagers(), null);
+ }
+
+ return ctx;
+ }
+
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+ if (debug)
+ System.setProperty("javax.net.debug", "all");
+
+ /*
+ * Get the customized arguments.
+ */
+ parseArguments(args);
+
+ /*
+ * Start the tests.
+ */
+ new DisabledShortDSAKeys();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ DisabledShortDSAKeys() throws Exception {
+ Exception startException = null;
+ try {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+ } catch (Exception e) {
+ startException = e;
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ if (serverThread != null) {
+ serverThread.join();
+ }
+ } else {
+ if (clientThread != null) {
+ clientThread.join();
+ }
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ * Which side threw the error?
+ */
+ Exception local;
+ Exception remote;
+
+ if (separateServerThread) {
+ remote = serverException;
+ local = clientException;
+ } else {
+ remote = clientException;
+ local = serverException;
+ }
+
+ Exception exception = null;
+
+ /*
+ * Check various exception conditions.
+ */
+ if ((local != null) && (remote != null)) {
+ // If both failed, return the curthread's exception.
+ local.initCause(remote);
+ exception = local;
+ } else if (local != null) {
+ exception = local;
+ } else if (remote != null) {
+ exception = remote;
+ } else if (startException != null) {
+ exception = startException;
+ }
+
+ /*
+ * If there was an exception *AND* a startException,
+ * output it.
+ */
+ if (exception != null) {
+ if (exception != startException && startException != null) {
+ exception.addSuppressed(startException);
+ }
+ throw exception;
+ }
+
+ // Fall-through: no exception to throw!
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ serverReady = true;
+ }
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
+ }
+ }
+}
diff --git a/openjdk/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/openjdk/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java
index f686cf7..9a8e028 100644
--- openjdk/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java
+++ openjdk/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java
@@ -41,7 +41,8 @@ import javax.net.ssl.SSLSocketFactory;
* @bug 8076221
* @summary Check if weak cipher suites are disabled
* @run main/othervm DisabledAlgorithms default
- * @run main/othervm DisabledAlgorithms empty
+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,secp192r1"
+ * DisabledAlgorithms empty
*/
public class DisabledAlgorithms {
@@ -97,6 +98,11 @@ public class DisabledAlgorithms {
System.out.println("jdk.tls.disabledAlgorithms = "
+ Security.getProperty("jdk.tls.disabledAlgorithms"));
+ // some of the certs in our test are weak; disable
+ Security.setProperty("jdk.certpath.disabledAlgorithms", "");
+ System.out.println("jdk.certpath.disabledAlgorithms = "
+ + Security.getProperty("jdk.cerpath.disabledAlgorithms"));
+
// check if RC4 cipher suites can be used
// if jdk.tls.disabledAlgorithms is empty
checkSuccess(rc4_ciphersuites);
@@ -224,6 +230,7 @@ public class DisabledAlgorithms {
socket.getSession().invalidate();
} catch (SSLHandshakeException e) {
System.out.println("Server: run: " + e);
+ e.printStackTrace();
sslError = true;
stopped = true;
} catch (IOException e) {
diff --git a/openjdk/jdk/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java b/openjdk/jdk/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java
new file mode 100644
index 0000000..9e7e692
--- /dev/null
+++ openjdk/jdk/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8148516
+ * @summary Improve the default strength of EC in JDK
+ * @run main/othervm ECCurvesconstraints PKIX
+ * @run main/othervm ECCurvesconstraints SunX509
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.Security;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.util.Base64;
+
+
+public class ECCurvesconstraints {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = false;
+
+ /*
+ * Where do we find the keystores?
+ */
+ // Certificates and key used in the test.
+ //
+ // EC curve: secp224k1
+ static String trustedCertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBCzCBugIEVz2lcjAKBggqhkjOPQQDAjAaMRgwFgYDVQQDDA93d3cuZXhhbXBs\n" +
+ "ZS5vcmcwHhcNMTYwNTE5MTEzNzM5WhcNMTcwNTE5MTEzNzM5WjAaMRgwFgYDVQQD\n" +
+ "DA93d3cuZXhhbXBsZS5vcmcwTjAQBgcqhkjOPQIBBgUrgQQAIAM6AAT68uovMZ8f\n" +
+ "KARn5NOjvieJaq6h8zHYkM9w5DuN0kkOo4KBhke06EkQj0nvQQcSvppTV6RoDLY4\n" +
+ "djAKBggqhkjOPQQDAgNAADA9AhwMNIujM0R0llpPH6d89d1S3VRGH/78ovc+zw51\n" +
+ "Ah0AuZ1YlQkUbrJIzkuPSICxz5UfCWPe+7w4as+wiA==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Private key in the format of PKCS#8
+ static String targetPrivateKey =
+ "MIGCAgEAMBAGByqGSM49AgEGBSuBBAAgBGswaQIBAQQdAPbckc86mgW/zexB1Ajq\n" +
+ "38HntWOjdxL6XSoiAsWgBwYFK4EEACChPAM6AAT68uovMZ8fKARn5NOjvieJaq6h\n" +
+ "8zHYkM9w5DuN0kkOo4KBhke06EkQj0nvQQcSvppTV6RoDLY4dg==";
+
+ static String[] serverCerts = {trustedCertStr};
+ static String[] serverKeys = {targetPrivateKey};
+ static String[] clientCerts = {trustedCertStr};
+ static String[] clientKeys = {targetPrivateKey};
+
+ static char passphrase[] = "passphrase".toCharArray();
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLContext context = generateSSLContext(false);
+ SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket)sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
+ try {
+ sslSocket.setSoTimeout(5000);
+ sslSocket.setSoLinger(true, 5);
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write('A');
+ sslOS.flush();
+
+ throw new Exception("EC curve secp224k1 should be disabled");
+ } catch (SSLHandshakeException she) {
+ // expected exception: no cipher suites in common
+ System.out.println("Expected exception: " + she);
+ } finally {
+ sslSocket.close();
+ sslServerSocket.close();
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLContext context = generateSSLContext(true);
+ SSLSocketFactory sslsf = context.getSocketFactory();
+
+ SSLSocket sslSocket =
+ (SSLSocket)sslsf.createSocket("localhost", serverPort);
+
+ try {
+ sslSocket.setSoTimeout(5000);
+ sslSocket.setSoLinger(true, 5);
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write('B');
+ sslOS.flush();
+ sslIS.read();
+
+ throw new Exception("EC curve secp224k1 should be disabled");
+ } catch (SSLHandshakeException she) {
+ // expected exception: Received fatal alert
+ System.out.println("Expected exception: " + she);
+ } finally {
+ sslSocket.close();
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+ private static String tmAlgorithm; // trust manager
+
+ private static void parseArguments(String[] args) {
+ tmAlgorithm = args[0];
+ }
+
+ private static SSLContext generateSSLContext(boolean isClient)
+ throws Exception {
+
+ // generate certificate from cert string
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ // create a key store
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+
+ // import the trused cert
+ ByteArrayInputStream is =
+ new ByteArrayInputStream(trustedCertStr.getBytes());
+ Certificate trusedCert = cf.generateCertificate(is);
+ is.close();
+
+ ks.setCertificateEntry("Export Signer", trusedCert);
+
+ String[] certStrs = null;
+ String[] keyStrs = null;
+ if (isClient) {
+ certStrs = clientCerts;
+ keyStrs = clientKeys;
+ } else {
+ certStrs = serverCerts;
+ keyStrs = serverKeys;
+ }
+
+ for (int i = 0; i < certStrs.length; i++) {
+ // generate the private key.
+ String keySpecStr = keyStrs[i];
+ PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+ Base64.getMimeDecoder().decode(keySpecStr));
+ KeyFactory kf = KeyFactory.getInstance("EC");
+ ECPrivateKey priKey =
+ (ECPrivateKey)kf.generatePrivate(priKeySpec);
+
+ // generate certificate chain
+ String keyCertStr = certStrs[i];
+ is = new ByteArrayInputStream(keyCertStr.getBytes());
+ Certificate keyCert = cf.generateCertificate(is);
+ is.close();
+
+ Certificate[] chain = new Certificate[2];
+ chain[0] = keyCert;
+ chain[1] = trusedCert;
+
+ // import the key entry.
+ ks.setKeyEntry("key-entry-" + i, priKey, passphrase, chain);
+ }
+
+ // create SSL context
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+ tmf.init(ks);
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+ kmf.init(ks, passphrase);
+
+ ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ ks = null;
+
+ return ctx;
+ }
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+ if (debug) {
+ System.setProperty("javax.net.debug", "all");
+ }
+
+ /*
+ * Get the customized arguments.
+ */
+ parseArguments(args);
+
+ /*
+ * Start the tests.
+ */
+ new ECCurvesconstraints();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ ECCurvesconstraints() throws Exception {
+ try {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+ } catch (Exception e) {
+ // swallow for now. Show later
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ * Which side threw the error?
+ */
+ Exception local;
+ Exception remote;
+ String whichRemote;
+
+ if (separateServerThread) {
+ remote = serverException;
+ local = clientException;
+ whichRemote = "server";
+ } else {
+ remote = clientException;
+ local = serverException;
+ whichRemote = "client";
+ }
+
+ /*
+ * If both failed, return the curthread's exception, but also
+ * print the remote side Exception
+ */
+ if ((local != null) && (remote != null)) {
+ System.out.println(whichRemote + " also threw:");
+ remote.printStackTrace();
+ System.out.println();
+ throw local;
+ }
+
+ if (remote != null) {
+ throw remote;
+ }
+
+ if (local != null) {
+ throw local;
+ }
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died, because of " + e);
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ serverReady = true;
+ }
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died, because of " + e);
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
+ }
+ }
+}
diff --git a/openjdk/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java b/openjdk/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java
new file mode 100644
index 0000000..a58bc70
--- /dev/null
+++ openjdk/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8166591
+ * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra
+ * is very fast (Trackpad, Retina only)
+ * @run main/manual/othervm TooMuchWheelRotationEventsTest
+ */
+public class TooMuchWheelRotationEventsTest {
+
+ private static volatile boolean testResult = false;
+ private static volatile CountDownLatch countDownLatch;
+ private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
+ + "Try to check the issue on Mac OS X 10.12 Sierra with trackpad"
+ + " on Retina display.\n"
+ + "\n"
+ + "If the trackpad is not supported, press PASS\n"
+ + "\n"
+ + "Use the trackpad to slightly scroll the JTextArea horizontally and vertically.\n"
+ + "If the text area is scrolled too fast press FAIL, else press PASS.";
+
+ public static void main(String args[]) throws Exception {
+ countDownLatch = new CountDownLatch(1);
+
+ SwingUtilities.invokeLater(TooMuchWheelRotationEventsTest::createUI);
+ countDownLatch.await(15, TimeUnit.MINUTES);
+
+ if (!testResult) {
+ throw new RuntimeException("Test fails!");
+ }
+ }
+
+ private static void createUI() {
+
+ final JFrame mainFrame = new JFrame("Trackpad scrolling test");
+ GridBagLayout layout = new GridBagLayout();
+ JPanel mainControlPanel = new JPanel(layout);
+ JPanel resultButtonPanel = new JPanel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ JPanel testPanel = createTestPanel();
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(testPanel, gbc);
+
+ JTextArea instructionTextArea = new JTextArea();
+ instructionTextArea.setText(INSTRUCTIONS);
+ instructionTextArea.setEditable(false);
+ instructionTextArea.setBackground(Color.white);
+
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ JButton passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ testResult = true;
+ mainFrame.dispose();
+ countDownLatch.countDown();
+
+ });
+
+ JButton failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+
+ mainFrame.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+ mainFrame.setVisible(true);
+ }
+
+ private static JPanel createTestPanel() {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ JTextArea textArea = new JTextArea(20, 20);
+ textArea.setText(getLongString());
+ JScrollPane scrollPane = new JScrollPane(textArea);
+ panel.add(scrollPane);
+ return panel;
+ }
+
+ private static String getLongString() {
+
+ String lowCaseString = getLongString('a', 'z');
+ String upperCaseString = getLongString('A', 'Z');
+ String digitsString = getLongString('0', '9');
+
+ int repeat = 30;
+ StringBuilder lowCaseBuilder = new StringBuilder();
+ StringBuilder upperCaseBuilder = new StringBuilder();
+ StringBuilder digitsBuilder = new StringBuilder();
+
+ for (int i = 0; i < repeat; i++) {
+ lowCaseBuilder.append(lowCaseString).append(' ');
+ upperCaseBuilder.append(upperCaseString).append(' ');
+ digitsBuilder.append(digitsString).append(' ');
+ }
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 200; i++) {
+ builder.append(upperCaseBuilder).append('\n')
+ .append(lowCaseBuilder).append('\n')
+ .append(digitsBuilder).append("\n\n\n");
+ }
+
+ return builder.toString();
+ }
+
+ private static String getLongString(char c1, char c2) {
+
+ char[] chars = new char[c2 - c1 + 1];
+ for (char i = c1; i <= c2; i++) {
+ chars[i - c1] = i;
+ }
+ return new String(chars);
+ }
+}
diff --git a/openjdk/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java b/openjdk/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java
new file mode 100644
index 0000000..cc05b56
--- /dev/null
+++ openjdk/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8151893
+ * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property
+ * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom
+ */
+
+import java.security.Security;
+import java.util.List;
+import java.util.Arrays;
+import org.jcp.xml.dsig.internal.dom.Policy;
+
+public class SecureValidationPolicy {
+
+ public static void main(String[] args) throws Exception {
+
+ List<String> restrictedSchemes = Arrays.asList("file:/tmp/foo",
+ "http://java.com", "https://java.com");
+ List<String> restrictedAlgs = Arrays.asList(
+ "http://www.w3.org/TR/1999/REC-xslt-19991116",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-md5",
+ "http://www.w3.org/2001/04/xmldsig-more#hmac-md5",
+ "http://www.w3.org/2001/04/xmldsig-more#md5");
+
+ // Test expected defaults
+ System.out.println("Testing defaults");
+ if (!Policy.restrictNumTransforms(6)) {
+ throw new Exception("maxTransforms not enforced");
+ }
+ if (!Policy.restrictNumReferences(31)) {
+ throw new Exception("maxReferences not enforced");
+ }
+ for (String scheme : restrictedSchemes) {
+ if (!Policy.restrictReferenceUriScheme(scheme)) {
+ throw new Exception(scheme + " scheme not restricted");
+ }
+ }
+ for (String alg : restrictedAlgs) {
+ if (!Policy.restrictAlg(alg)) {
+ throw new Exception(alg + " alg not restricted");
+ }
+ }
+ if (!Policy.restrictDuplicateIds()) {
+ throw new Exception("noDuplicateIds not enforced");
+ }
+ if (!Policy.restrictRetrievalMethodLoops()) {
+ throw new Exception("noRetrievalMethodLoops not enforced");
+ }
+ }
+}
diff --git a/openjdk/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java b/openjdk/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
index 13b07a5..327594d 100644
--- openjdk/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
+++ openjdk/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
@@ -25,6 +25,7 @@ package jdk.testlibrary;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
@@ -43,7 +44,8 @@ public final class JarUtils {
/**
- * Create jar file with specified files from specified location.
+ * Create jar file with specified files. If a specified file does not exist,
+ * a new jar entry will be created with the file name itself as the content.
*/
public static void createJar(String dest, Path filesLocation,
String... fileNames) throws IOException {
@@ -63,6 +65,8 @@ public final class JarUtils {
}
try (FileInputStream fis = new FileInputStream(file)) {
Utils.transferBetweenStreams(fis, jos);
+ } catch (FileNotFoundException e) {
+ jos.write(fileName.getBytes());
}
}
}
@@ -78,7 +82,17 @@ public final class JarUtils {
}
/**
- * Add specified files to existing jar file.
+ * Add or remove specified files to existing jar file. If a specified file
+ * to be updated or added does not exist, the jar entry will be created
+ * with the file name itself as the content.
+ *
+ * @param src the original jar file name
+ * @param dest the new jar file name
+ * @param files the files to update. The list is broken into 2 groups
+ * by a "-" string. The files before in the 1st group will
+ * be either updated or added. The files in the 2nd group
+ * will be removed. If no "-" exists, all files belong to
+ * the 1st group.
*/
public static void updateJar(String src, String dest, String... files)
throws IOException {
@@ -94,8 +108,11 @@ public final class JarUtils {
JarEntry entry = entries.nextElement();
String name = entry.getName();
boolean found = false;
+ boolean update = true;
for (String file : files) {
- if (name.equals(file)) {
+ if (file.equals("-")) {
+ update = false;
+ } else if (name.equals(file)) {
updatedFiles.add(file);
found = true;
break;
@@ -103,11 +120,18 @@ public final class JarUtils {
}
if (found) {
+ if (update) {
System.out.println(String.format("Updating %s with %s",
dest, name));
jos.putNextEntry(new JarEntry(name));
try (FileInputStream fis = new FileInputStream(name)) {
Utils.transferBetweenStreams(fis, jos);
+ } catch (FileNotFoundException e) {
+ jos.write(name.getBytes());
+ }
+ } else {
+ System.out.println(String.format("Removing %s from %s",
+ name, dest));
}
} else {
System.out.println(String.format("Copying %s to %s",
@@ -121,12 +145,17 @@ public final class JarUtils {
// append new files
for (String file : files) {
+ if (file.equals("-")) {
+ break;
+ }
if (!updatedFiles.contains(file)) {
System.out.println(String.format("Adding %s with %s",
dest, file));
jos.putNextEntry(new JarEntry(file));
try (FileInputStream fis = new FileInputStream(file)) {
Utils.transferBetweenStreams(fis, jos);
+ } catch (FileNotFoundException e) {
+ jos.write(file.getBytes());
}
}
}
diff --git a/openjdk/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java b/openjdk/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java
new file mode 100644
index 0000000..68e0d49
--- /dev/null
+++ openjdk/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import sun.reflect.ReflectionFactory;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.TestNG;
+
+/*
+ * @test
+ * @bug 8137058 8164908 8168980
+ * @run testng ReflectionFactoryTest
+ * @run testng/othervm/policy=security.policy ReflectionFactoryTest
+ * @summary Basic test for the unsupported ReflectionFactory
+ */
+
+public class ReflectionFactoryTest {
+
+ // Initialized by init()
+ static ReflectionFactory factory;
+
+ @DataProvider(name = "ClassConstructors")
+ static Object[][] classConstructors() {
+ return new Object[][] {
+ {Object.class},
+ {Foo.class},
+ {Bar.class},
+ };
+ }
+
+ @BeforeClass
+ static void init() {
+ factory = ReflectionFactory.getReflectionFactory();
+ }
+
+ /**
+ * Test that the correct Constructor is selected and run.
+ * @param type type of object to create
+ * @throws NoSuchMethodException - error
+ * @throws InstantiationException - error
+ * @throws IllegalAccessException - error
+ * @throws InvocationTargetException - error
+ */
+ @Test(dataProvider="ClassConstructors")
+ static void testConstructor(Class<?> type)
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException
+ {
+ @SuppressWarnings("unchecked")
+ Constructor<?> c = factory.newConstructorForSerialization(type);
+
+ Object o = c.newInstance();
+ Assert.assertEquals(o.getClass(), type, "Instance is wrong type");
+ if (o instanceof Foo) {
+ Foo foo = (Foo)o;
+ foo.check();
+ }
+ }
+
+ @DataProvider(name = "NonSerialConstructors")
+ static Object[][] constructors() throws NoSuchMethodException {
+ return new Object[][] {
+ {Foo.class, Object.class.getDeclaredConstructor()},
+ {Foo.class, Foo.class.getDeclaredConstructor()},
+ {Baz.class, Object.class.getDeclaredConstructor()},
+ {Baz.class, Foo.class.getDeclaredConstructor()},
+ {Baz.class, Baz.class.getDeclaredConstructor()}
+ };
+ }
+
+ /**
+ * Tests that the given Constructor, in the hierarchy, is run.
+ */
+ @Test(dataProvider="NonSerialConstructors")
+ static void testNonSerializableConstructor(Class<?> cl,
+ Constructor<?> constructorToCall)
+ throws ReflectiveOperationException
+ {
+ @SuppressWarnings("unchecked")
+ Constructor<?> c = factory.newConstructorForSerialization(cl,
+ constructorToCall);
+
+ Object o = c.newInstance();
+ Assert.assertEquals(o.getClass(), cl, "Instance is wrong type");
+
+ int expectedFoo = 0;
+ int expectedBaz = 0;
+ if (constructorToCall.getName().equals("ReflectionFactoryTest$Foo")) {
+ expectedFoo = 1;
+ } else if (constructorToCall.getName().equals("ReflectionFactoryTest$Baz")) {
+ expectedFoo = 1;
+ expectedBaz = 4;
+ }
+
+ Assert.assertEquals(((Foo)o).foo(), expectedFoo);
+ if (o instanceof Baz) {
+ Assert.assertEquals(((Baz)o).baz(), expectedBaz);
+ }
+ }
+
+ static class Foo {
+ private int foo;
+ public Foo() {
+ this.foo = 1;
+ }
+
+ public String toString() {
+ return "foo: " + foo;
+ }
+
+ public void check() {
+ int expectedFoo = 1;
+ Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
+ }
+
+ public int foo() { return foo; }
+ }
+
+ static class Bar extends Foo implements Serializable {
+ private static final long serialVersionUID = 3L;
+
+ private int bar;
+ public Bar() {
+ this.bar = 1;
+ }
+
+ public String toString() {
+ return super.toString() + ", bar: " + bar;
+ }
+
+ public void check() {
+ super.check();
+ int expectedBar = 0;
+ Assert.assertEquals(bar, expectedBar, "bar() constructor not run");
+ }
+ }
+
+ static class Baz extends Foo {
+ private static final long serialVersionUID = 4L;
+
+ private final int baz;
+ public Baz() { this.baz = 4; }
+ public int baz() { return baz; }
+ }
+
+ /**
+ * Test newConstructorForExternalization returns the constructor and it can be called.
+ * @throws NoSuchMethodException - error
+ * @throws InstantiationException - error
+ * @throws IllegalAccessException - error
+ * @throws InvocationTargetException - error
+ */
+ @Test
+ static void newConstructorForExternalization()
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ Constructor<?> cons = factory.newConstructorForExternalization(Ext.class);
+ Ext ext = (Ext)cons.newInstance();
+ Assert.assertEquals(ext.ext, 1, "Constructor not run");
+ }
+
+ static class Ext implements Externalizable {
+ private static final long serialVersionUID = 1L;
+
+ int ext;
+
+ public Ext() {
+ ext = 1;
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {}
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {}
+ }
+
+ @Test
+ static void testReadWriteObjectForSerialization() throws Throwable {
+ MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class);
+ Assert.assertNotNull(readObjectMethod, "readObjectMethod not found");
+
+ MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class);
+ Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found");
+
+ MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class);
+ Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found");
+
+ MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class);
+ Assert.assertNotNull(readResolveMethod, "readResolveMethod not found");
+
+ MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class);
+ Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found");
+
+ byte[] data = null;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ Ser ser = new Ser();
+
+ writeReplaceMethod.invoke(ser);
+ Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called");
+ Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called");
+
+ writeObjectMethod.invoke(ser, oos);
+ Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called");
+ Assert.assertTrue(ser.writeObjectCalled, "writeObject not called");
+ oos.flush();
+ data = baos.toByteArray();
+ }
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ Ser ser2 = new Ser();
+
+ readObjectMethod.invoke(ser2, ois);
+ Assert.assertTrue(ser2.readObjectCalled, "readObject not called");
+ Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called");
+ Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+ readObjectNoDataMethod.invoke(ser2, ois);
+ Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+ Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+ Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+ readResolveMethod.invoke(ser2);
+ Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+ Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+ Assert.assertTrue(ser2.readResolveCalled, "readResolve not called");
+ }
+ }
+
+ @Test
+ static void hasStaticInitializer() {
+ boolean actual = factory.hasStaticInitializerForSerialization(Ser.class);
+ Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong");
+ }
+
+ static class Ser implements Serializable {
+ private static final long serialVersionUID = 2L;
+ static {
+ // Define a static class initialization method
+ }
+
+ boolean readObjectCalled = false;
+ boolean readObjectNoDataCalled = false;
+ boolean writeObjectCalled = false;
+ boolean readResolveCalled = false;
+ boolean writeReplaceCalled = false;
+
+ public Ser() {}
+
+ private void readObject(ObjectInputStream ois) throws IOException {
+ Assert.assertFalse(writeObjectCalled, "readObject called too many times");
+ readObjectCalled = ois.readBoolean();
+ }
+
+ private void readObjectNoData(ObjectInputStream ois) throws IOException {
+ Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times");
+ readObjectNoDataCalled = true;
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ Assert.assertFalse(writeObjectCalled, "writeObject called too many times");
+ writeObjectCalled = true;
+ oos.writeBoolean(writeObjectCalled);
+ }
+
+ private Object writeReplace() {
+ Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times");
+ writeReplaceCalled = true;
+ return this;
+ }
+
+ private Object readResolve() {
+ Assert.assertFalse(readResolveCalled, "readResolve called too many times");
+ readResolveCalled = true;
+ return this;
+ }
+ }
+
+ /**
+ * Test the constructor of OptionalDataExceptions.
+ */
+ @Test
+ static void newOptionalDataException() {
+ OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true);
+ Assert.assertTrue(ode.eof, "eof wrong");
+ ode = factory.newOptionalDataExceptionForSerialization(false);
+ Assert.assertFalse(ode.eof, "eof wrong");
+
+ }
+
+
+
+ // Main can be used to run the tests from the command line with only testng.jar.
+ @SuppressWarnings("raw_types")
+ @Test(enabled = false)
+ public static void main(String[] args) {
+ Class<?>[] testclass = {ReflectionFactoryTest.class};
+ TestNG testng = new TestNG();
+ testng.setTestClasses(testclass);
+ testng.run();
+ }
+}
diff --git a/openjdk/jdk/test/sun/reflect/ReflectionFactory/security.policy b/openjdk/jdk/test/sun/reflect/ReflectionFactory/security.policy
new file mode 100644
index 0000000..8c30f3b
--- /dev/null
+++ openjdk/jdk/test/sun/reflect/ReflectionFactory/security.policy
@@ -0,0 +1,11 @@
+// Individual Permissions for ReflectionFactoryTest
+grant {
+ // Permissions needed to run the test
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
+
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+ permission java.lang.RuntimePermission "reflectionFactoryAccess";
+};
diff --git a/openjdk/jdk/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java b/openjdk/jdk/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java
new file mode 100644
index 0000000..285a2b7
--- /dev/null
+++ openjdk/jdk/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.InvalidClassException;
+import java.io.Serializable;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.UnmarshalException;
+
+import java.util.Objects;
+
+import sun.misc.ObjectInputFilter;
+import sun.rmi.server.UnicastServerRef;
+import sun.rmi.server.UnicastServerRef2;
+import sun.rmi.transport.LiveRef;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @modules java.rmi/sun.rmi.registry
+ * java.rmi/sun.rmi.server
+ * java.rmi/sun.rmi.transport
+ * java.rmi/sun.rmi.transport.tcp
+ * @run testng/othervm FilterUSRTest
+ * @summary Check objects exported with ObjectInputFilters via internal UnicastServerRef(2)
+ */
+public class FilterUSRTest {
+
+ /**
+ * Data to test serialFilter call counts.
+ * - name
+ * - Object
+ * - expected count of calls to checkInput.
+ *
+ * @return array of test data
+ */
+ @DataProvider(name = "bindData")
+ static Object[][] bindObjects() {
+ Object[][] data = {
+ {"SimpleString", "SimpleString", 0},
+ {"String", new XX("now is the time"), 1},
+ {"String[]", new XX(new String[3]), 3},
+ {"Long[4]", new XX(new Long[4]), 3},
+ {"RejectME", new XX(new RejectME()), -1},
+ };
+ return data;
+ }
+
+ /*
+ * Test exporting an object with a serialFilter using UnicastServerRef.exportObject().
+ * Send some objects and check the number of calls to the serialFilter.
+ */
+ @Test(dataProvider = "bindData")
+ public void UnicastServerRef(String name, Object obj, int expectedFilterCount) throws RemoteException {
+ try {
+ RemoteImpl impl = RemoteImpl.create();
+ UnicastServerRef ref = new UnicastServerRef(new LiveRef(0), impl.checker);
+
+ Echo client = (Echo) ref.exportObject(impl, null, false);
+
+ int count = client.filterCount(obj);
+ System.out.printf("count: %d, obj: %s%n", count, obj);
+ Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls");
+ } catch (RemoteException rex) {
+ if (expectedFilterCount == -1 &&
+ UnmarshalException.class.equals(rex.getCause().getClass()) &&
+ InvalidClassException.class.equals(rex.getCause().getCause().getClass())) {
+ return; // normal expected exception
+ }
+ rex.printStackTrace();
+ Assert.fail("unexpected remote exception", rex);
+ } catch (Exception ex) {
+ Assert.fail("unexpected exception", ex);
+ }
+ }
+
+ /*
+ * Test exporting an object with a serialFilter using UnicastServerRef2.exportObject()
+ * with explicit (but null) SocketFactories.
+ * Send some objects and check the number of calls to the serialFilter.
+ */
+ @Test(dataProvider = "bindData")
+ public void UnicastServerRef2(String name, Object obj, int expectedFilterCount) throws RemoteException {
+ try {
+ RemoteImpl impl = RemoteImpl.create();
+ UnicastServerRef2 ref = new UnicastServerRef2(0, null, null, impl.checker);
+
+ Echo client = (Echo) ref.exportObject(impl, null, false);
+
+ int count = client.filterCount(obj);
+ System.out.printf("count: %d, obj: %s%n", count, obj);
+ Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls");
+ } catch (RemoteException rex) {
+ if (expectedFilterCount == -1 &&
+ UnmarshalException.class.equals(rex.getCause().getClass()) &&
+ InvalidClassException.class.equals(rex.getCause().getCause().getClass())) {
+ return; // normal expected exception
+ }
+ rex.printStackTrace();
+ Assert.fail("unexpected remote exception", rex);
+ } catch (Exception rex) {
+ Assert.fail("unexpected exception", rex);
+ }
+ }
+
+ /**
+ * A simple Serializable holding an object that is passed by value.
+ * It and its contents are checked by the filter.
+ */
+ static class XX implements Serializable {
+ private static final long serialVersionUID = 362498820763181265L;
+
+ final Object obj;
+
+ XX(Object obj) {
+ this.obj = obj;
+ }
+
+ public String toString() {
+ return super.toString() + "//" + Objects.toString(obj);
+ }
+ }
+
+ interface Echo extends Remote {
+ int filterCount(Object obj) throws RemoteException;
+ }
+
+ /**
+ * This remote object just counts the calls to the serialFilter
+ * and returns it. The caller can check the number against
+ * what was expected for the object passed as an argument.
+ * A new RemoteImpl is used for each test so the count starts at zero again.
+ */
+ static class RemoteImpl implements Echo {
+
+ private static final long serialVersionUID = 1L;
+
+ transient Checker checker;
+
+ static RemoteImpl create() throws RemoteException {
+ RemoteImpl impl = new RemoteImpl(new Checker());
+ return impl;
+ }
+
+ private RemoteImpl(Checker checker) throws RemoteException {
+ this.checker = checker;
+ }
+
+ public int filterCount(Object obj) throws RemoteException {
+ return checker.count();
+ }
+
+ }
+
+ /**
+ * A ObjectInputFilter that just counts when it is called.
+ */
+ static class Checker implements ObjectInputFilter {
+ int count;
+
+ @Override
+ public Status checkInput(ObjectInputFilter.FilterInfo info) {
+ if (info.serialClass() == RejectME.class) {
+ return Status.REJECTED;
+ }
+ count++;
+ return Status.UNDECIDED;
+ }
+
+ public int count() {
+ return count;
+ }
+ }
+
+ /**
+ * A class to be rejected by the filter.
+ */
+ static class RejectME implements Serializable {
+ private static final long serialVersionUID = 2L;
+ }
+
+}
diff --git a/openjdk/jdk/test/sun/security/ec/TestEC.java b/openjdk/jdk/test/sun/security/ec/TestEC.java
index 3dcad24..28d9648 100644
--- openjdk/jdk/test/sun/security/ec/TestEC.java
+++ openjdk/jdk/test/sun/security/ec/TestEC.java
@@ -35,7 +35,7 @@
* @library ../pkcs11/sslecc
* @library ../../../java/security/testlibrary
* @compile -XDignore.symbol.file TestEC.java
- * @run main/othervm TestEC
+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC
*/
import java.security.NoSuchProviderException;
diff --git a/openjdk/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java b/openjdk/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
index f754148..e19930b 100644
--- openjdk/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
+++ openjdk/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
@@ -33,7 +33,8 @@
* @author Andreas Sterbenz
* @library ..
* @library ../../../../java/security/testlibrary
- * @run main/othervm ClientJSSEServerJSSE
+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1"
+ * ClientJSSEServerJSSE
*/
import java.security.*;
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestChannel.java b/openjdk/jdk/test/sun/security/smartcardio/TestChannel.java
index 3dc4029..4cc79da 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestChannel.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestChannel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,11 @@ public class TestChannel extends Utils {
public static void main(String[] args) throws Exception {
CardTerminal terminal = getTerminal(args);
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
+ }
// establish a connection with the card
Card card = terminal.connect("T=0");
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestConnect.java b/openjdk/jdk/test/sun/security/smartcardio/TestConnect.java
index b533b93..1dcd85b 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestConnect.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestConnect.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,23 +39,12 @@ import javax.smartcardio.CardTerminal;
public class TestConnect extends Utils {
public static void main(String[] args) throws Exception {
- TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null, "SunPCSC");
- System.out.println(factory);
-
- List<CardTerminal> terminals = factory.terminals().list();
- System.out.println("Terminals: " + terminals);
- if (terminals.isEmpty()) {
- throw new Exception("No card terminals available");
- }
- CardTerminal terminal = terminals.get(0);
-
- if (terminal.isCardPresent() == false) {
- System.out.println("*** Insert card");
- if (terminal.waitForCardPresent(20 * 1000) == false) {
- throw new Exception("no card available");
- }
+ CardTerminal terminal = getTerminal(args, "SunPCSC");
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
}
- System.out.println("card present: " + terminal.isCardPresent());
Card card = terminal.connect("*");
System.out.println("card: " + card);
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestConnectAgain.java b/openjdk/jdk/test/sun/security/smartcardio/TestConnectAgain.java
index 9a2889e..24fac1c 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestConnectAgain.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestConnectAgain.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,11 @@ public class TestConnectAgain extends Utils {
public static void main(String[] args) throws Exception {
CardTerminal terminal = getTerminal(args);
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
+ }
Card card = terminal.connect("T=0");
CardChannel channel = card.getBasicChannel();
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestControl.java b/openjdk/jdk/test/sun/security/smartcardio/TestControl.java
index 5160755..e5fb18f 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestControl.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestControl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,11 @@ public class TestControl extends Utils {
public static void main(String[] args) throws Exception {
CardTerminal terminal = getTerminal(args);
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
+ }
// establish a connection with the card
Card card = terminal.connect("T=0");
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestDefault.java b/openjdk/jdk/test/sun/security/smartcardio/TestDefault.java
index 0808df4..eb345e9 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestDefault.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestDefault.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,12 @@ public class TestDefault {
TerminalFactory factory = TerminalFactory.getDefault();
System.out.println("Type: " + factory.getType());
List<CardTerminal> terminals = factory.terminals().list();
- System.out.println("Terminals: " + terminals);
if (terminals.isEmpty()) {
- throw new Exception("no terminals");
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
}
+ System.out.println("Terminals: " + terminals);
System.out.println("OK.");
}
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestDirect.java b/openjdk/jdk/test/sun/security/smartcardio/TestDirect.java
index 3dde7c3..5c09ea9 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestDirect.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestDirect.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,12 @@ public class TestDirect {
public static void main(String[] args) throws Exception {
TerminalFactory terminalFactory = TerminalFactory.getDefault();
List<CardTerminal> cardTerminals = terminalFactory.terminals().list();
- System.out.println("Terminals: " + cardTerminals);
if (cardTerminals.isEmpty()) {
- throw new Exception("No card terminals available");
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
}
+ System.out.println("Terminals: " + cardTerminals);
CardTerminal cardTerminal = cardTerminals.get(0);
Card card = cardTerminal.connect("DIRECT");
card.disconnect(true);
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestExclusive.java b/openjdk/jdk/test/sun/security/smartcardio/TestExclusive.java
index a4c75e6..7187f77 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestExclusive.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestExclusive.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,11 @@ public class TestExclusive extends Utils {
public static void main(String[] args) throws Exception {
CardTerminal terminal = getTerminal(args);
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
+ }
// establish a connection with the card
Card card = terminal.connect("T=0");
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestMultiplePresent.java b/openjdk/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
index 271cb21..cbbcc43 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,12 @@ public class TestMultiplePresent {
public static void main(String[] args) throws Exception {
Utils.setLibrary(args);
- TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
+ TerminalFactory factory = Utils.getTerminalFactory(null);
+ if (factory == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
+ }
System.out.println(factory);
CardTerminals terminals = factory.terminals();
@@ -49,7 +54,9 @@ public class TestMultiplePresent {
boolean multipleReaders = true;
if (list.size() < 2) {
if (list.isEmpty()) {
- throw new Exception("no terminals");
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
}
System.out.println("Only one reader present, using simplified test");
multipleReaders = false;
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestPresent.java b/openjdk/jdk/test/sun/security/smartcardio/TestPresent.java
index fbfebd5..4e4c648 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestPresent.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestPresent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@ import java.util.List;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
-public class TestPresent {
+public class TestPresent extends Utils {
private static class Timer {
private long time = System.currentTimeMillis();
@@ -66,15 +66,12 @@ public class TestPresent {
}
public static void main(String[] args) throws Exception {
- TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
- System.out.println(factory);
-
- List<CardTerminal> terminals = factory.terminals().list();
- System.out.println("Terminals: " + terminals);
- if (terminals.isEmpty()) {
- throw new Exception("No card terminals available");
+ CardTerminal terminal = getTerminal(args);
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
}
- CardTerminal terminal = terminals.get(0);
while (terminal.isCardPresent()) {
System.out.println("*** Remove card!");
diff --git a/openjdk/jdk/test/sun/security/smartcardio/TestTransmit.java b/openjdk/jdk/test/sun/security/smartcardio/TestTransmit.java
index 9092683..c49904b 100644
--- openjdk/jdk/test/sun/security/smartcardio/TestTransmit.java
+++ openjdk/jdk/test/sun/security/smartcardio/TestTransmit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,11 @@ public class TestTransmit extends Utils {
public static void main(String[] args) throws Exception {
CardTerminal terminal = getTerminal(args);
+ if (terminal == null) {
+ System.out.println("Skipping the test: " +
+ "no card terminals available");
+ return;
+ }
Card card = terminal.connect("T=0");
CardChannel channel = card.getBasicChannel();
diff --git a/openjdk/jdk/test/sun/security/smartcardio/Utils.java b/openjdk/jdk/test/sun/security/smartcardio/Utils.java
index b4edbcc..036b8dd 100644
--- openjdk/jdk/test/sun/security/smartcardio/Utils.java
+++ openjdk/jdk/test/sun/security/smartcardio/Utils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.io.StringReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import javax.smartcardio.CardTerminal;
@@ -43,26 +44,59 @@ public class Utils {
}
}
+ static TerminalFactory getTerminalFactory(String provName) throws Exception {
+ try {
+ TerminalFactory factory = (provName == null)
+ ? TerminalFactory.getInstance("PC/SC", null)
+ : TerminalFactory.getInstance("PC/SC", null, provName);
+ System.out.println(factory);
+ return factory;
+ } catch (NoSuchAlgorithmException e) {
+ Throwable cause = e.getCause();
+ if (cause != null && cause.getMessage().startsWith("PC/SC not available")) {
+ return null;
+ }
+ throw e;
+ }
+ }
+
static CardTerminal getTerminal(String[] args) throws Exception {
+ return getTerminal(args, null);
+ }
+
+ static CardTerminal getTerminal(String[] args, String provider) throws Exception {
setLibrary(args);
- TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
- System.out.println(factory);
+ try {
+ TerminalFactory factory = (provider == null)
+ ? TerminalFactory.getInstance("PC/SC", null)
+ : TerminalFactory.getInstance("PC/SC", null, provider);
+ System.out.println(factory);
+
+ List<CardTerminal> terminals = factory.terminals().list();
+ System.out.println("Terminals: " + terminals);
+ if (terminals.isEmpty()) {
+ return null;
+ }
+ CardTerminal terminal = terminals.get(0);
- List<CardTerminal> terminals = factory.terminals().list();
- System.out.println("Terminals: " + terminals);
- if (terminals.isEmpty()) {
- throw new Exception("No card terminals available");
- }
- CardTerminal terminal = terminals.get(0);
+ if (terminal.isCardPresent() == false) {
+ System.out.println("*** Insert card");
+ if (terminal.waitForCardPresent(20 * 1000) == false) {
+ throw new Exception("no card available");
+ }
+ }
+ System.out.println("card present: " + terminal.isCardPresent());
+
+ return terminal;
- if (terminal.isCardPresent() == false) {
- System.out.println("*** Insert card");
- if (terminal.waitForCardPresent(20 * 1000) == false) {
- throw new Exception("no card available");
+ } catch (NoSuchAlgorithmException e) {
+ Throwable cause = e.getCause();
+ if (cause != null && cause.getMessage().startsWith("PC/SC not available")) {
+ return null;
}
+ throw e;
}
- return terminal;
}
static final byte[] C1 = parse("00 A4 04 00 07 A0 00 00 00 62 81 01 00");
diff --git a/openjdk/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java b/openjdk/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
index 8a5db10..1cf22f0 100644
--- openjdk/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
+++ openjdk/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,12 @@
/*
* @test
- * @bug 6916074
+ * @bug 6916074 8170131
* @summary Add support for TLS 1.2
- * @run main/othervm PKIXExtendedTM
+ * @run main/othervm PKIXExtendedTM 0
+ * @run main/othervm PKIXExtendedTM 1
+ * @run main/othervm PKIXExtendedTM 2
+ * @run main/othervm PKIXExtendedTM 3
*/
import java.net.*;
@@ -42,6 +45,7 @@ import java.security.KeyStore;
import java.security.KeyFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathValidatorException;
import java.security.spec.*;
import java.security.interfaces.*;
import java.math.BigInteger;
@@ -792,20 +796,85 @@ public class PKIXExtendedTM {
volatile Exception serverException = null;
volatile Exception clientException = null;
- public static void main(String args[]) throws Exception {
+ static class Test {
+ String tlsDisAlgs;
+ String certPathDisAlgs;
+ boolean fail;
+ Test(String tlsDisAlgs, String certPathDisAlgs, boolean fail) {
+ this.tlsDisAlgs = tlsDisAlgs;
+ this.certPathDisAlgs = certPathDisAlgs;
+ this.fail = fail;
+ }
+ }
+
+ static Test[] tests = {
// MD5 is used in this test case, don't disable MD5 algorithm.
+ new Test(
+ "SSLv3, RC4, DH keySize < 768",
+ "MD2, RSA keySize < 1024",
+ false),
+ // Disable MD5 but only if cert chains back to public root CA, should
+ // pass because the MD5 cert in this test case is issued by test CA
+ new Test(
+ "SSLv3, RC4, DH keySize < 768",
+ "MD2, MD5 jdkCA, RSA keySize < 1024",
+ false),
+ // Disable MD5 alg via TLS property and expect failure
+ new Test(
+ "SSLv3, MD5, RC4, DH keySize < 768",
+ "MD2, RSA keySize < 1024",
+ true),
+ // Disable MD5 alg via certpath property and expect failure
+ new Test(
+ "SSLv3, RC4, DH keySize < 768",
+ "MD2, MD5, RSA keySize < 1024",
+ true),
+ };
+
+ public static void main(String args[]) throws Exception {
+ if (args.length != 1) {
+ throw new Exception("Incorrect number of arguments");
+ }
+ Test test = tests[Integer.parseInt(args[0])];
+ Security.setProperty("jdk.tls.disabledAlgorithms", test.tlsDisAlgs);
Security.setProperty("jdk.certpath.disabledAlgorithms",
- "MD2, RSA keySize < 1024");
- Security.setProperty("jdk.tls.disabledAlgorithms",
- "SSLv3, RC4, DH keySize < 768");
+ test.certPathDisAlgs);
- if (debug)
+ if (debug) {
System.setProperty("javax.net.debug", "all");
+ }
/*
* Start the tests.
*/
- new PKIXExtendedTM();
+ try {
+ new PKIXExtendedTM();
+ if (test.fail) {
+ throw new Exception("Expected MD5 certificate to be blocked");
+ }
+ } catch (Exception e) {
+ if (test.fail) {
+ // find expected cause
+ boolean correctReason = false;
+ Throwable cause = e.getCause();
+ while (cause != null) {
+ if (cause instanceof CertPathValidatorException) {
+ CertPathValidatorException cpve =
+ (CertPathValidatorException)cause;
+ if (cpve.getReason() == CertPathValidatorException.BasicReason.ALGORITHM_CONSTRAINED) {
+ correctReason = true;
+ break;
+ }
+ }
+ cause = cause.getCause();
+ }
+ if (!correctReason) {
+ throw new Exception("Unexpected exception", e);
+ }
+ } else {
+ throw e;
+ }
+ }
}
Thread clientThread = null;
diff --git a/openjdk/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java b/openjdk/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
index 8c92a2b..516eb9c 100644
--- openjdk/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
+++ openjdk/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
* @bug 7188657
* @summary There should be a way to reorder the JSSE ciphers
* @run main/othervm UseCipherSuitesOrder
- * TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ * TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA
*/
import java.io.*;
diff --git a/openjdk/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java b/openjdk/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
index 5e08f76..812732e 100644
--- openjdk/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
+++ openjdk/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
@@ -26,7 +26,8 @@
* @bug 4496785
* @summary Verify that all ciphersuites work in all configurations
* @author Andreas Sterbenz
- * @run main/othervm/timeout=300 ClientJSSEServerJSSE
+ * @run main/othervm/timeout=300 -Djdk.tls.namedGroups="secp256r1,secp192r1"
+ * ClientJSSEServerJSSE
*/
import java.security.Security;
diff --git a/openjdk/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java b/openjdk/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
index bc4d6ed..321df20 100644
--- openjdk/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
+++ openjdk/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
@@ -22,25 +22,31 @@
*/
import com.sun.net.httpserver.*;
-import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import sun.misc.IOUtils;
+import jdk.testlibrary.*;
+import jdk.testlibrary.JarUtils;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.PKCS9Attribute;
@@ -52,11 +58,22 @@ import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
+/*
+ * @test
+ * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688
+ * @summary checking response of timestamp
+ * @modules java.base/sun.security.pkcs
+ * java.base/sun.security.timestamp
+ * java.base/sun.security.x509
+ * java.base/sun.security.util
+ * java.base/sun.security.tools.keytool
+ * @library /lib/testlibrary
+ * @run main/timeout=600 TimestampCheck
+ */
public class TimestampCheck {
- static final String TSKS = "tsks";
- static final String JAR = "old.jar";
- static final String defaultPolicyId = "2.3.4.5";
+ static final String defaultPolicyId = "2.3.4";
+ static String host = null;
static class Handler implements HttpHandler, AutoCloseable {
@@ -75,11 +92,7 @@ public class TimestampCheck {
t.getRequestBody().read(input);
try {
- int path = 0;
- if (t.getRequestURI().getPath().length() > 1) {
- path = Integer.parseInt(
- t.getRequestURI().getPath().substring(1));
- }
+ String path = t.getRequestURI().getPath().substring(1);
byte[] output = sign(input, path);
Headers out = t.getResponseHeaders();
out.set("Content-Type", "application/timestamp-reply");
@@ -97,24 +110,9 @@ public class TimestampCheck {
/**
* @param input The data to sign
* @param path different cases to simulate, impl on URL path
- * 0: normal
- * 1: Missing nonce
- * 2: Different nonce
- * 3: Bad digets octets in messageImprint
- * 4: Different algorithmId in messageImprint
- * 5: whole chain in cert set
- * 6: extension is missing
- * 7: extension is non-critical
- * 8: extension does not have timestamping
- * 9: no cert in response
- * 10: normal
- * 11: always return default policy id
- * 12: normal
- * otherwise: normal
* @returns the signed
*/
- byte[] sign(byte[] input, int path) throws Exception {
- // Read TSRequest
+ byte[] sign(byte[] input, String path) throws Exception {
DerValue value = new DerValue(input);
System.err.println("\nIncoming Request\n===================");
System.err.println("Version: " + value.data.getInteger());
@@ -138,36 +136,35 @@ public class TimestampCheck {
}
}
- // Write TSResponse
System.err.println("\nResponse\n===================");
- KeyStore ks = KeyStore.getInstance("JKS");
- try (FileInputStream fis = new FileInputStream(keystore)) {
- ks.load(fis, "changeit".toCharArray());
- }
+ FileInputStream is = new FileInputStream(keystore);
+ KeyStore ks = KeyStore.getInstance("JCEKS");
+ ks.load(is, "changeit".toCharArray());
+ is.close();
String alias = "ts";
- if (path == 6) alias = "tsbad1";
- if (path == 7) alias = "tsbad2";
- if (path == 8) alias = "tsbad3";
+ if (path.startsWith("bad") || path.equals("weak")) {
+ alias = "ts" + path;
+ }
- if (path == 11) {
+ if (path.equals("diffpolicy")) {
policyId = new ObjectIdentifier(defaultPolicyId);
}
DerOutputStream statusInfo = new DerOutputStream();
statusInfo.putInteger(0);
- DerOutputStream token = new DerOutputStream();
AlgorithmId[] algorithms = {aid};
Certificate[] chain = ks.getCertificateChain(alias);
- X509Certificate[] signerCertificateChain = null;
+ X509Certificate[] signerCertificateChain;
X509Certificate signer = (X509Certificate)chain[0];
- if (path == 5) { // Only case 5 uses full chain
+
+ if (path.equals("fullchain")) { // Only case 5 uses full chain
signerCertificateChain = new X509Certificate[chain.length];
for (int i=0; i<chain.length; i++) {
signerCertificateChain[i] = (X509Certificate)chain[i];
}
- } else if (path == 9) {
+ } else if (path.equals("nocert")) {
signerCertificateChain = new X509Certificate[0];
} else {
signerCertificateChain = new X509Certificate[1];
@@ -179,11 +176,11 @@ public class TimestampCheck {
tst.putInteger(1);
tst.putOID(policyId);
- if (path != 3 && path != 4) {
+ if (!path.equals("baddigest") && !path.equals("diffalg")) {
tst.putDerValue(messageImprint);
} else {
byte[] data = messageImprint.toByteArray();
- if (path == 4) {
+ if (path.equals("diffalg")) {
data[6] = (byte)0x01;
} else {
data[data.length-1] = (byte)0x01;
@@ -198,10 +195,10 @@ public class TimestampCheck {
Calendar cal = Calendar.getInstance();
tst.putGeneralizedTime(cal.getTime());
- if (path == 2) {
+ if (path.equals("diffnonce")) {
tst.putInteger(1234);
- } else if (path == 1) {
- // do nothing
+ } else if (path.equals("nononce")) {
+ // no noce
} else {
tst.putInteger(nonce);
}
@@ -212,6 +209,8 @@ public class TimestampCheck {
DerOutputStream tstInfo2 = new DerOutputStream();
tstInfo2.putOctetString(tstInfo.toByteArray());
+ // Always use the same algorithm at timestamp signing
+ // so it is different from the hash algorithm.
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign((PrivateKey)(ks.getKey(
alias, "changeit".toCharArray())));
@@ -229,12 +228,11 @@ public class TimestampCheck {
SignerInfo signerInfo = new SignerInfo(
new X500Name(signer.getIssuerX500Principal().getName()),
signer.getSerialNumber(),
- aid, AlgorithmId.get("RSA"), sig.sign());
+ AlgorithmId.get("SHA-1"), AlgorithmId.get("RSA"), sig.sign());
SignerInfo[] signerInfos = {signerInfo};
- PKCS7 p7 =
- new PKCS7(algorithms, contentInfo, signerCertificateChain,
- signerInfos);
+ PKCS7 p7 = new PKCS7(algorithms, contentInfo,
+ signerCertificateChain, signerInfos);
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
p7.encodeSignedData(p7out);
@@ -293,42 +291,79 @@ public class TimestampCheck {
stop();
}
}
- public static void main(String[] args) throws Exception {
- try (Handler tsa = Handler.init(0, TSKS);) {
+
+ public static void main(String[] args) throws Throwable {
+
+ prepare();
+
+ try (Handler tsa = Handler.init(0, "tsks");) {
tsa.start();
int port = tsa.getPort();
- String cmd;
- // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
- // nonce generation in timestamping request. Not avaibale on
- // Windows and defaults to thread seed generator, not too bad.
- if (System.getProperty("java.home").endsWith("jre")) {
- cmd = System.getProperty("java.home") + "/../bin/jarsigner";
- } else {
- cmd = System.getProperty("java.home") + "/bin/jarsigner";
- }
-
- cmd += " -J-Djava.security.egd=file:/dev/./urandom"
- + " -debug -keystore " + TSKS + " -storepass changeit"
- + " -tsa http://localhost:" + port + "/%d"
- + " -signedjar new_%d.jar " + JAR + " old";
+ host = "http://localhost:" + port + "/";
if (args.length == 0) { // Run this test
- jarsigner(cmd, 0, true); // Success, normal call
- jarsigner(cmd, 1, false); // These 4 should fail
- jarsigner(cmd, 2, false);
- jarsigner(cmd, 3, false);
- jarsigner(cmd, 4, false);
- jarsigner(cmd, 5, true); // Success, 6543440 solved.
- jarsigner(cmd, 6, false); // tsbad1
- jarsigner(cmd, 7, false); // tsbad2
- jarsigner(cmd, 8, false); // tsbad3
- jarsigner(cmd, 9, false); // no cert in timestamp
- jarsigner(cmd + " -tsapolicyid 1.2.3.4", 10, true);
- checkTimestamp("new_10.jar", "1.2.3.4", "SHA-256");
- jarsigner(cmd + " -tsapolicyid 1.2.3.5", 11, false);
- jarsigner(cmd + " -tsadigestalg SHA", 12, true);
- checkTimestamp("new_12.jar", defaultPolicyId, "SHA-1");
+ sign("none")
+ .shouldContain("is not timestamped")
+ .shouldHaveExitValue(0);
+
+ sign("badku")
+ .shouldHaveExitValue(0);
+ checkBadKU("badku.jar");
+
+ sign("normal")
+ .shouldNotContain("is not timestamped")
+ .shouldHaveExitValue(0);
+
+ sign("nononce")
+ .shouldHaveExitValue(1);
+ sign("diffnonce")
+ .shouldHaveExitValue(1);
+ sign("baddigest")
+ .shouldHaveExitValue(1);
+ sign("diffalg")
+ .shouldHaveExitValue(1);
+ sign("fullchain")
+ .shouldHaveExitValue(0); // Success, 6543440 solved.
+ sign("bad1")
+ .shouldHaveExitValue(1);
+ sign("bad2")
+ .shouldHaveExitValue(1);
+ sign("bad3")
+ .shouldHaveExitValue(1);
+ sign("nocert")
+ .shouldHaveExitValue(1);
+
+ sign("policy", "-tsapolicyid", "1.2.3")
+ .shouldHaveExitValue(0);
+ checkTimestamp("policy.jar", "1.2.3", "SHA-256");
+
+ sign("diffpolicy", "-tsapolicyid", "1.2.3")
+ .shouldHaveExitValue(1);
+
+ sign("tsaalg", "-tsadigestalg", "SHA")
+ .shouldHaveExitValue(0);
+ checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1");
+
+ sign("weak", "-digestalg", "MD2",
+ "-sigalg", "MD2withRSA", "-tsadigestalg", "MD2")
+ .shouldHaveExitValue(0);
+ checkWeak("weak.jar");
+
+ signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5")
+ .shouldHaveExitValue(0);
+ checkHalfWeak("halfWeak.jar");
+
+ // sign with DSA key
+ signWithAliasAndTsa("sign1", "old.jar", "dsakey")
+ .shouldHaveExitValue(0);
+ // sign with RSAkeysize < 1024
+ signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize")
+ .shouldHaveExitValue(0);
+ checkMultiple("sign2.jar");
+
+ // When .SF or .RSA is missing or invalid
+ checkMissingOrInvalidFiles("normal.jar");
} else { // Run as a standalone server
System.err.println("Press Enter to quit server");
System.in.read();
@@ -336,6 +371,132 @@ public class TimestampCheck {
}
}
+ private static void checkMissingOrInvalidFiles(String s)
+ throws Throwable {
+ JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF");
+ verify("1.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Missing signature-related file META-INF/OLD.SF");
+ JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA");
+ verify("2.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Missing block file for signature-related file META-INF/OLD.SF");
+ JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF");
+ verify("3.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Unparsable signature-related file META-INF/OLD.SF");
+ JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA");
+ verify("4.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Unparsable signature-related file META-INF/OLD.RSA");
+ }
+
+ static OutputAnalyzer jarsigner(List<String> extra)
+ throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
+ .addVMArg("-Duser.language=en")
+ .addVMArg("-Duser.country=US")
+ .addToolArg("-keystore")
+ .addToolArg("tsks")
+ .addToolArg("-storepass")
+ .addToolArg("changeit");
+ for (String s : extra) {
+ if (s.startsWith("-J")) {
+ launcher.addVMArg(s.substring(2));
+ } else {
+ launcher.addToolArg(s);
+ }
+ }
+ System.err.println("COMMAND: ");
+ for (String cmd : launcher.getCommand()) {
+ System.err.print(cmd + " ");
+ }
+ System.err.println();
+ return ProcessTools.executeCommand(launcher.getCommand());
+ }
+
+ static OutputAnalyzer verify(String file, String... extra)
+ throws Throwable {
+ List<String> args = new ArrayList<>();
+ args.add("-verify");
+ args.add(file);
+ args.addAll(Arrays.asList(extra));
+ return jarsigner(args);
+ }
+
+ static void checkBadKU(String file) throws Throwable {
+ System.err.println("BadKU: " + file);
+ verify(file)
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("re-run jarsigner with debug enabled");
+ verify(file, "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("Signed by")
+ .shouldContain("treated as unsigned")
+ .shouldContain("re-run jarsigner with debug enabled");
+ verify(file, "-J-Djava.security.debug=jar")
+ .shouldHaveExitValue(0)
+ .shouldContain("SignatureException: Key usage restricted")
+ .shouldContain("treated as unsigned")
+ .shouldContain("re-run jarsigner with debug enabled");
+ }
+
+ static void checkWeak(String file) throws Throwable {
+ verify(file)
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldMatch("weak algorithm that is now disabled.")
+ .shouldMatch("Re-run jarsigner with the -verbose option for more details");
+ verify(file, "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldMatch("weak algorithm that is now disabled by")
+ .shouldMatch("Digest algorithm: .*weak")
+ .shouldMatch("Signature algorithm: .*weak")
+ .shouldMatch("Timestamp digest algorithm: .*weak")
+ .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
+ .shouldMatch("Timestamp signature algorithm: .*key.*weak");
+ verify(file, "-J-Djava.security.debug=jar")
+ .shouldHaveExitValue(0)
+ .shouldMatch("SignatureException:.*Disabled");
+ }
+
+ static void checkHalfWeak(String file) throws Throwable {
+ verify(file)
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldMatch("weak algorithm that is now disabled.")
+ .shouldMatch("Re-run jarsigner with the -verbose option for more details");
+ verify(file, "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldMatch("weak algorithm that is now disabled by")
+ .shouldMatch("Digest algorithm: .*weak")
+ .shouldNotMatch("Signature algorithm: .*weak")
+ .shouldNotMatch("Timestamp digest algorithm: .*weak")
+ .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
+ .shouldNotMatch("Timestamp signature algorithm: .*key.*weak");
+ }
+
+ static void checkMultiple(String file) throws Throwable {
+ verify(file)
+ .shouldHaveExitValue(0)
+ .shouldContain("jar verified");
+ verify(file, "-verbose", "-certs")
+ .shouldHaveExitValue(0)
+ .shouldContain("jar verified")
+ .shouldMatch("X.509.*CN=dsakey")
+ .shouldNotMatch("X.509.*CN=weakkeysize")
+ .shouldMatch("Signed by .*CN=dsakey")
+ .shouldMatch("Signed by .*CN=weakkeysize")
+ .shouldMatch("Signature algorithm: .*key.*weak");
+ }
+
static void checkTimestamp(String file, String policyId, String digestAlg)
throws Exception {
try (JarFile jf = new JarFile(file)) {
@@ -362,41 +523,75 @@ public class TimestampCheck {
}
}
+ static int which = 0;
+
/**
- * @param cmd the command line (with a hole to plug in)
- * @param path the path in the URL, i.e, http://localhost/path
- * @param expected if this command should succeed
+ * @param extra more args given to jarsigner
*/
- static void jarsigner(String cmd, int path, boolean expected)
- throws Exception {
- System.err.println("Test " + path);
- Process p = Runtime.getRuntime().exec(String.format(cmd, path, path));
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(p.getErrorStream()));
- while (true) {
- String s = reader.readLine();
- if (s == null) break;
- System.err.println(s);
- }
+ static OutputAnalyzer sign(String path, String... extra)
+ throws Throwable {
+ String alias = path.equals("badku") ? "badku" : "old";
+ return signWithAliasAndTsa(path, "old.jar", alias, extra);
+ }
- // Will not see noTimestamp warning
- boolean seeWarning = false;
- reader = new BufferedReader(
- new InputStreamReader(p.getInputStream()));
- while (true) {
- String s = reader.readLine();
- if (s == null) break;
- System.err.println(s);
- if (s.indexOf("Warning:") >= 0) {
- seeWarning = true;
- }
- }
- int result = p.waitFor();
- if (expected && result != 0 || !expected && result == 0) {
- throw new Exception("Failed");
- }
- if (seeWarning) {
- throw new Exception("See warning");
+ static OutputAnalyzer signWithAliasAndTsa (String path, String jar,
+ String alias, String...extra) throws Throwable {
+ which++;
+ System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra));
+ List<String> args = new ArrayList<>();
+ args.add("-J-Djava.security.egd=file:/dev/./urandom");
+ args.add("-debug");
+ args.add("-signedjar");
+ args.add(path + ".jar");
+ args.add(jar);
+ args.add(alias);
+ if (!path.equals("none") && !path.equals("badku")) {
+ args.add("-tsa");
+ args.add(host + path);
+ }
+ args.addAll(Arrays.asList(extra));
+ return jarsigner(args);
+ }
+
+ static void prepare() throws Exception {
+ jdk.testlibrary.JarUtils.createJar("old.jar", "A");
+ Files.deleteIfExists(Paths.get("tsks"));
+ keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
+ keytool("-alias old -genkeypair -dname CN=old");
+ keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey");
+ keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize");
+ keytool("-alias badku -genkeypair -dname CN=badku");
+ keytool("-alias ts -genkeypair -dname CN=ts");
+ keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1");
+ keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1");
+ keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2");
+ keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
+
+ gencert("old");
+ gencert("dsakey");
+ gencert("weakkeysize");
+ gencert("badku", "-ext ku:critical=keyAgreement");
+ gencert("ts", "-ext eku:critical=ts");
+ gencert("tsweak", "-ext eku:critical=ts");
+ gencert("tsbad1");
+ gencert("tsbad2", "-ext eku=ts");
+ gencert("tsbad3", "-ext eku:critical=cs");
+ }
+
+ static void gencert(String alias, String... extra) throws Exception {
+ keytool("-alias " + alias + " -certreq -file " + alias + ".req");
+ String genCmd = "-gencert -alias ca -infile " +
+ alias + ".req -outfile " + alias + ".cert";
+ for (String s : extra) {
+ genCmd += " " + s;
}
+ keytool(genCmd);
+ keytool("-alias " + alias + " -importcert -file " + alias + ".cert");
+ }
+
+ static void keytool(String cmd) throws Exception {
+ cmd = "-keystore tsks -storepass changeit -keypass changeit " +
+ "-keyalg rsa -validity 200 " + cmd;
+ sun.security.tools.keytool.Main.main(cmd.split(" "));
}
}
diff --git a/openjdk/jdk/test/sun/security/tools/jarsigner/ts.sh b/openjdk/jdk/test/sun/security/tools/jarsigner/ts.sh
deleted file mode 100644
index 6cee680..0000000
--- openjdk/jdk/test/sun/security/tools/jarsigner/ts.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6543842 6543440 6939248 8009636 8024302
-# @summary checking response of timestamp
-#
-# @run shell/timeout=600 ts.sh
-
-# Run for a long time because jarsigner with timestamp needs to create a
-# 64-bit random number and it might be extremely slow on a machine with
-# not enough entropy pool
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
- Windows_* )
- FS="\\"
- ;;
- * )
- FS="/"
- ;;
-esac
-
-if [ "${TESTSRC}" = "" ] ; then
- TESTSRC="."
-fi
-if [ "${TESTJAVA}" = "" ] ; then
- JAVAC_CMD=`which javac`
- TESTJAVA=`dirname $JAVAC_CMD`/..
-fi
-
-JAR="${TESTJAVA}${FS}bin${FS}jar"
-JAVA="${TESTJAVA}${FS}bin${FS}java"
-JAVAC="${TESTJAVA}${FS}bin${FS}javac"
-KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200"
-
-rm tsks
-echo Nothing > A
-rm old.jar
-$JAR cvf old.jar A
-
-# ca is CA
-# old is signer for code
-# ts is signer for timestamp
-# tsbad1 has no extendedKeyUsage
-# tsbad2's extendedKeyUsage is non-critical
-# tsbad3's extendedKeyUsage has no timestamping
-
-$KT -alias ca -genkeypair -ext bc -dname CN=CA
-$KT -alias old -genkeypair -dname CN=old
-$KT -alias ts -genkeypair -dname CN=ts
-$KT -alias tsbad1 -genkeypair -dname CN=tsbad1
-$KT -alias tsbad2 -genkeypair -dname CN=tsbad2
-$KT -alias tsbad3 -genkeypair -dname CN=tsbad3
-$KT -alias ts -certreq | \
- $KT -alias ca -gencert -ext eku:critical=ts | \
- $KT -alias ts -importcert
-$KT -alias tsbad1 -certreq | \
- $KT -alias ca -gencert | \
- $KT -alias tsbad1 -importcert
-$KT -alias tsbad2 -certreq | \
- $KT -alias ca -gencert -ext eku=ts | \
- $KT -alias tsbad2 -importcert
-$KT -alias tsbad3 -certreq | \
- $KT -alias ca -gencert -ext eku:critical=cs | \
- $KT -alias tsbad3 -importcert
-
-$JAVAC -XDignore.symbol.file -d . ${TESTSRC}/TimestampCheck.java
-$JAVA ${TESTVMOPTS} TimestampCheck
-
diff --git a/openjdk/jdk/test/sun/security/tools/jarsigner/warnings/Test.java b/openjdk/jdk/test/sun/security/tools/jarsigner/warnings/Test.java
index 6018a6d..43ced17 100644
--- openjdk/jdk/test/sun/security/tools/jarsigner/warnings/Test.java
+++ openjdk/jdk/test/sun/security/tools/jarsigner/warnings/Test.java
@@ -22,6 +22,11 @@
*/
import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* Base class.
@@ -175,4 +180,38 @@ public abstract class Test {
}
analyzer.shouldContain(JAR_SIGNED);
}
+
+ protected OutputAnalyzer keytool(String... cmd) throws Throwable {
+ return tool(KEYTOOL, cmd);
+ }
+
+ protected OutputAnalyzer jarsigner(String... cmd) throws Throwable {
+ return tool(JARSIGNER, cmd);
+ }
+
+ private OutputAnalyzer tool(String tool, String... args) throws Throwable {
+ List<String> cmd = new ArrayList<>();
+ cmd.add(tool);
+ cmd.add("-J-Duser.language=en");
+ cmd.add("-J-Duser.country=US");
+ cmd.addAll(Arrays.asList(args));
+ return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()]));
+ }
+
+ protected OutputAnalyzer keytool(String... cmd) throws Throwable {
+ return tool(KEYTOOL, cmd);
+ }
+
+ protected OutputAnalyzer jarsigner(String... cmd) throws Throwable {
+ return tool(JARSIGNER, cmd);
+ }
+
+ private OutputAnalyzer tool(String tool, String... args) throws Throwable {
+ List<String> cmd = new ArrayList<>();
+ cmd.add(tool);
+ cmd.add("-J-Duser.language=en");
+ cmd.add("-J-Duser.country=US");
+ cmd.addAll(Arrays.asList(args));
+ return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()]));
+ }
}
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/VERSION b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/VERSION
index 6bf3661..3fbffda 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/VERSION
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2016f
+tzdata2016i
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/africa b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/africa
index b523dc3..cbde238 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/africa
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/africa
@@ -487,7 +487,7 @@ Zone Africa/Monrovia -0:43:08 - LMT 1882
# http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/
#
# From Paul Eggert (2013-10-25):
-# For now, assume they're reverting to the pre-2012 rules of permanent UTC+2.
+# For now, assume they're reverting to the pre-2012 rules of permanent UT +02.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Libya 1951 only - Oct 14 2:00 1:00 S
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/antarctica b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/antarctica
index e12c764..2398ac5 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/antarctica
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/antarctica
@@ -33,9 +33,7 @@
# http://www.spri.cam.ac.uk/bob/periant.htm
# for information.
# Unless otherwise specified, we have no time zone information.
-#
-# Except for the French entries,
-# I made up all time zone abbreviations mentioned here; corrections welcome!
+
# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
# Argentina - year-round bases
@@ -52,7 +50,7 @@
# previously sealers and scientific personnel wintered
# Margaret Turner reports
# http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
-# (1999-09-30) that they're UTC+5, with no DST;
+# (1999-09-30) that they're UT +05, with no DST;
# presumably this is when they have visitors.
#
# year-round bases
@@ -89,25 +87,29 @@
# Background:
# http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
+# From Steffen Thorsen (2016-10-28):
+# Australian Antarctica Division informed us that Casey changed time
+# zone to UTC+11 in "the morning of 22nd October 2016".
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - -00 1969
- 8:00 - AWST 2009 Oct 18 2:00
- # Australian Western Std Time
- 11:00 - CAST 2010 Mar 5 2:00 # Casey Time
- 8:00 - AWST 2011 Oct 28 2:00
- 11:00 - CAST 2012 Feb 21 17:00u
- 8:00 - AWST
+ 8:00 - +08 2009 Oct 18 2:00
+ 11:00 - +11 2010 Mar 5 2:00
+ 8:00 - +08 2011 Oct 28 2:00
+ 11:00 - +11 2012 Feb 21 17:00u
+ 8:00 - +08 2016 Oct 22
+ 11:00 - +11
Zone Antarctica/Davis 0 - -00 1957 Jan 13
- 7:00 - DAVT 1964 Nov # Davis Time
+ 7:00 - +07 1964 Nov
0 - -00 1969 Feb
- 7:00 - DAVT 2009 Oct 18 2:00
- 5:00 - DAVT 2010 Mar 10 20:00u
- 7:00 - DAVT 2011 Oct 28 2:00
- 5:00 - DAVT 2012 Feb 21 20:00u
- 7:00 - DAVT
+ 7:00 - +07 2009 Oct 18 2:00
+ 5:00 - +05 2010 Mar 10 20:00u
+ 7:00 - +07 2011 Oct 28 2:00
+ 5:00 - +05 2012 Feb 21 20:00u
+ 7:00 - +07
Zone Antarctica/Mawson 0 - -00 1954 Feb 13
- 6:00 - MAWT 2009 Oct 18 2:00 # Mawson Time
- 5:00 - MAWT
+ 6:00 - +06 2009 Oct 18 2:00
+ 5:00 - +05
# References:
# Casey Weather (1998-02-26)
# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
@@ -161,7 +163,7 @@ Zone Antarctica/Mawson 0 - -00 1954 Feb 13
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
- 5:00 - TFT # ISO code TF Time
+ 5:00 - +05
#
# year-round base in the main continent
# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
@@ -172,9 +174,9 @@ Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/DumontDUrville 0 - -00 1947
- 10:00 - PMT 1952 Jan 14 # Port-Martin Time
+ 10:00 - +10 1952 Jan 14
0 - -00 1956 Nov
- 10:00 - DDUT # Dumont-d'Urville Time
+ 10:00 - +10
# France & Italy - year-round base
# Concordia, -750600+1232000, since 2005
@@ -200,7 +202,7 @@ Zone Antarctica/DumontDUrville 0 - -00 1947
# station of Japan, it's appropriate for the principal location.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Syowa 0 - -00 1957 Jan 29
- 3:00 - SYOT # Syowa Time
+ 3:00 - +03
# See:
# NIPR Antarctic Research Activities (1999-08-17)
# http://www.nipr.ac.jp/english/ara01.html
@@ -237,17 +239,17 @@ Zone Antarctica/Syowa 0 - -00 1957 Jan 29
# correct, but they should be quite close to the actual dates.
#
# From Paul Eggert (2014-03-21):
-# The CET-switching Troll rules require zic from tzcode 2014b or later, so as
+# The CET-switching Troll rules require zic from tz 2014b or later, so as
# suggested by Bengt-Inge Larsson comment them out for now, and approximate
# with only UTC and CEST. Uncomment them when 2014b is more prevalent.
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-#Rule Troll 2005 max - Mar 1 1:00u 1:00 CET
-Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST
-#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 CET
-#Rule Troll 2004 max - Nov 7 1:00u 0:00 UTC
+#Rule Troll 2005 max - Mar 1 1:00u 1:00 +01
+Rule Troll 2005 max - Mar lastSun 1:00u 2:00 +02
+#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 +01
+#Rule Troll 2004 max - Nov 7 1:00u 0:00 +00
# Remove the following line when uncommenting the above '#Rule' lines.
-Rule Troll 2004 max - Oct lastSun 1:00u 0:00 UTC
+Rule Troll 2004 max - Oct lastSun 1:00u 0:00 +00
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Troll 0 - -00 2005 Feb 12
0:00 Troll %s
@@ -288,10 +290,10 @@ Zone Antarctica/Troll 0 - -00 2005 Feb 12
# changes during the year and does not necessarily correspond to mean
# solar noon. So the Vostok time might have been whatever the clocks
# happened to be during their visit. So we still don't really know what time
-# it is at Vostok. But we'll guess UTC+6.
+# it is at Vostok. But we'll guess +06.
#
Zone Antarctica/Vostok 0 - -00 1957 Dec 16
- 6:00 - VOST # Vostok time
+ 6:00 - +06
# S Africa - year-round bases
# Marion Island, -4653+03752
@@ -324,7 +326,7 @@ Zone Antarctica/Vostok 0 - -00 1957 Dec 16
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Rothera 0 - -00 1976 Dec 1
- -3:00 - ROTT # Rothera time
+ -3:00 - -03
# Uruguay - year round base
# Artigas, King George Island, -621104-0585107
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/asia b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/asia
index 35ac37c..7d54032 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/asia
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/asia
@@ -139,13 +139,11 @@ Zone Asia/Kabul 4:36:48 - LMT 1890
# http://www.worldtimezone.com/dst_news/dst_news_armenia03.html
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2
- 3:00 - YERT 1957 Mar # Yerevan Time
- 4:00 RussiaAsia YER%sT 1991 Mar 31 2:00s
- 3:00 1:00 YERST 1991 Sep 23 # independence
- 3:00 RussiaAsia AM%sT 1995 Sep 24 2:00s
- 4:00 - AMT 1997
- 4:00 RussiaAsia AM%sT 2012 Feb 9
- 4:00 - AMT
+ 3:00 - +03 1957 Mar
+ 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
+ 3:00 RussiaAsia +03/+04 1995 Sep 24 2:00s
+ 4:00 - +04 1997
+ 4:00 RussiaAsia +04/+05
# Azerbaijan
@@ -166,13 +164,12 @@ Rule Azer 1997 2015 - Mar lastSun 4:00 1:00 S
Rule Azer 1997 2015 - Oct lastSun 5:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Baku 3:19:24 - LMT 1924 May 2
- 3:00 - BAKT 1957 Mar # Baku Time
- 4:00 RussiaAsia BAK%sT 1991 Mar 31 2:00s
- 3:00 1:00 BAKST 1991 Aug 30 # independence
- 3:00 RussiaAsia AZ%sT 1992 Sep lastSun 2:00s
- 4:00 - AZT 1996 # Azerbaijan Time
- 4:00 EUAsia AZ%sT 1997
- 4:00 Azer AZ%sT
+ 3:00 - +03 1957 Mar
+ 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
+ 3:00 RussiaAsia +03/+04 1992 Sep lastSun 2:00s
+ 4:00 - +04 1996
+ 4:00 EUAsia +04/+05 1997
+ 4:00 Azer +04/+05
# Bahrain
# See Asia/Qatar.
@@ -291,7 +288,7 @@ Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
# Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Rangoon 6:24:40 - LMT 1880 # or Yangon
+Zone Asia/Yangon 6:24:40 - LMT 1880 # or Rangoon
6:24:40 - RMT 1920 # Rangoon Mean Time?
6:30 - BURT 1942 May # Burma Time
9:00 - JST 1945 May 3
@@ -406,7 +403,7 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
# different - the occupied districts going by Tokyo time, an hour
# ahead of that prevailing in the rest of Shanghai." Guess that the
-# Xujiahui Observatory was under French control and stuck with UT+8.
+# Xujiahui Observatory was under French control and stuck with UT +08.
#
# In earlier versions of this file, China had many separate Zone entries, but
# this was based on what were apparently incorrect data in Shanks & Pottenger.
@@ -415,26 +412,26 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Proposed in 1918 and theoretically in effect until 1949 (although in practice
# mainly observed in coastal areas), the five zones were:
#
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT +08:30
# Asia/Harbin (currently a link to Asia/Shanghai)
# Heilongjiang (except Mohe county), Jilin
#
-# Zhongyuan Time ("Central plain Time") UT+8
+# Zhongyuan Time ("Central plain Time") UT +08
# Asia/Shanghai
# most of China
# This currently represents most other zones as well,
# as apparently these regions have been the same since 1970.
# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
-# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+# Guo says Shanghai switched to UT +08 "from the end of the 19th century".
#
-# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Long-shu Time (probably due to Long and Shu being two names of the area) UT +07
# Asia/Chongqing (currently a link to Asia/Shanghai)
# Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
# most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
# counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
# Yangchun, Yangjiang, Yu'nan, and Yunfu.
#
-# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Xin-zang Time ("Xinjiang-Tibet Time") UT +06
# Asia/Urumqi
# This currently represents Kunlun Time as well,
# as apparently the two regions have been the same since 1970.
@@ -447,7 +444,7 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
# Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
#
-# Kunlun Time UT+5.5
+# Kunlun Time UT +05:30
# Asia/Kashgar (currently a link to Asia/Urumqi)
# West Tibet, including Pulan, Aheqi, Shufu, Shule;
# West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
@@ -463,7 +460,7 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
#
# On the other hand, ethnic Uyghurs, who make up about half the
# population of Xinjiang, typically use "Xinjiang time" which is two
-# hours behind Beijing time, or UTC +0600. The government of the Xinjiang
+# hours behind Beijing time, or UT +06. The government of the Xinjiang
# Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
# local governments such as the Ürümqi city government use both times in
# publications, referring to what is popularly called Xinjiang time as
@@ -519,8 +516,8 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# having the same time as Beijing.
# From Paul Eggert (2014-06-30):
-# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
-# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# In the early days of the PRC, Tibet was given its own time zone (UT +06)
+# but this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
@@ -534,12 +531,12 @@ Rule PRC 1987 1991 - Apr Sun>=10 0:00 1:00 D
# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
# China, and tracking down all these organizations' timekeeping rules would be
# quite a trick. Approximate this lost history by a transition from LMT to
-# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# UT +06 at the start of 1928, the year of accession of the warlord Jin Shuren,
# which happens to be the date given by Shanks & Pottenger (no doubt as a
-# guess) as the transition from LMT. Ignore the usage of UT+8 before
-# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# guess) as the transition from LMT. Ignore the usage of +08 before
+# 1986-02-01 under the theory that the transition date to +08 is unknown and
# that the sort of users who prefer Asia/Urumqi now typically ignored the
-# UT+8 mandate back then.
+# +08 mandate back then.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
# Beijing time, used throughout China; represented by Shanghai.
@@ -744,7 +741,7 @@ Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30
# be found from historical government announcement database.
# From Paul Eggert (2014-07-03):
-# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# As per Yu-Cheng Chuang, say that Taiwan was at UT +09 from 1937-10-01
# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
@@ -797,9 +794,19 @@ Zone Asia/Macau 7:34:20 - LMT 1912 Jan 1
###############################################################################
# Cyprus
-#
+
# Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT.
+# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+
+# From Paul Eggert (2016-09-09):
+# Yesterday's Cyprus Mail reports that Northern Cyprus followed Turkey's
+# lead and switched from +02/+03 to +03 year-round.
+# http://cyprus-mail.com/2016/09/08/two-time-zones-cyprus-turkey-will-not-turn-clocks-back-next-month/
#
+# From Even Scharning (2016-10-31):
+# Looks like the time zone split in Cyprus went through last night.
+# http://cyprus-mail.com/2016/10/30/cyprus-new-division-two-time-zones-now-reality/
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Cyprus 1975 only - Apr 13 0:00 1:00 S
Rule Cyprus 1975 only - Oct 12 0:00 0 -
@@ -814,7 +821,10 @@ Rule Cyprus 1981 1998 - Mar lastSun 0:00 1:00 S
Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14
2:00 Cyprus EE%sT 1998 Sep
2:00 EUAsia EE%sT
-# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+Zone Asia/Famagusta 2:15:48 - LMT 1921 Nov 14
+ 2:00 Cyprus EE%sT 1998 Sep
+ 2:00 EUAsia EE%sT 2016 Sep 8
+ 3:00 - +03
# Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72.
# However, for various reasons many users expect to find it under Europe.
@@ -858,16 +868,15 @@ Link Asia/Nicosia Europe/Nicosia
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Tbilisi 2:59:11 - LMT 1880
2:59:11 - TBMT 1924 May 2 # Tbilisi Mean Time
- 3:00 - TBIT 1957 Mar # Tbilisi Time
- 4:00 RussiaAsia TBI%sT 1991 Mar 31 2:00s
- 3:00 1:00 TBIST 1991 Apr 9 # independence
- 3:00 RussiaAsia GE%sT 1992 # Georgia Time
- 3:00 E-EurAsia GE%sT 1994 Sep lastSun
- 4:00 E-EurAsia GE%sT 1996 Oct lastSun
- 4:00 1:00 GEST 1997 Mar lastSun
- 4:00 E-EurAsia GE%sT 2004 Jun 27
- 3:00 RussiaAsia GE%sT 2005 Mar lastSun 2:00
- 4:00 - GET
+ 3:00 - +03 1957 Mar
+ 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
+ 3:00 RussiaAsia +03/+04 1992
+ 3:00 E-EurAsia +03/+04 1994 Sep lastSun
+ 4:00 E-EurAsia +04/+05 1996 Oct lastSun
+ 4:00 1:00 +05 1997 Mar lastSun
+ 4:00 E-EurAsia +04/+05 2004 Jun 27
+ 3:00 RussiaAsia +03/+04 2005 Mar lastSun 2:00
+ 4:00 - +04
# East Timor
@@ -944,7 +953,7 @@ Zone Asia/Kolkata 5:53:28 - LMT 1880 # Kolkata
# These would be the earliest possible times for a change.
# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
# Traditionnelles, 1987, Paris) says that Java and Madura switched
-# from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
+# from UT +09 to +07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
# (Hollandia). For now, assume all Indonesian locations other than Jayapura
# switched on 1945-09-23.
#
@@ -955,11 +964,11 @@ Zone Asia/Kolkata 5:53:28 - LMT 1880 # Kolkata
# summary published by the Time and Frequency Laboratory of the
# Research Center for Calibration, Instrumentation and Metrology,
# Indonesia, <http://time.kim.lipi.go.id/time-eng.php> (2006-09-29).
-# The abbreviations are:
+# The time zone abbreviations and UT offsets are:
#
-# WIB - UTC+7 - Waktu Indonesia Barat (Indonesia western time)
-# WITA - UTC+8 - Waktu Indonesia Tengah (Indonesia central time)
-# WIT - UTC+9 - Waktu Indonesia Timur (Indonesia eastern time)
+# WIB - +07 - Waktu Indonesia Barat (Indonesia western time)
+# WITA - +08 - Waktu Indonesia Tengah (Indonesia central time)
+# WIT - +09 - Waktu Indonesia Timur (Indonesia eastern time)
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
# Java, Sumatra
@@ -1848,11 +1857,11 @@ Rule Kyrgyz 1997 2005 - Mar lastSun 2:30 1:00 S
Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
- 5:00 - FRUT 1930 Jun 21 # Frunze Time
- 6:00 RussiaAsia FRU%sT 1991 Mar 31 2:00s
- 5:00 1:00 FRUST 1991 Aug 31 2:00 # independence
- 5:00 Kyrgyz KG%sT 2005 Aug 12 # Kyrgyzstan Time
- 6:00 - KGT
+ 5:00 - +05 1930 Jun 21
+ 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s
+ 5:00 RussiaAsia +05/+06 1991 Aug 31 2:00
+ 5:00 Kyrgyz +05/+06 2005 Aug 12
+ 6:00 - +06
###############################################################################
@@ -1891,25 +1900,24 @@ Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S
Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
-# From Paul Eggert (2014-10-30):
+# From Paul Eggert (2016-08-23):
# The Korean Wikipedia entry gives the following sources for UT offsets:
#
-# 1908: Official Journal Article No. 3994 (Edict No. 5)
+# 1908: Official Journal Article No. 3994 (decree No. 5)
# 1912: Governor-General of Korea Official Gazette Issue No. 367
# (Announcement No. 338)
# 1954: Presidential Decree No. 876 (1954-03-17)
# 1961: Law No. 676 (1961-08-07)
-# 1987: Law No. 3919 (1986-12-31)
#
-# The Wikipedia entry also has confusing information about a change
-# to UT+9 in April 1910, but then what would be the point of the later change
-# to UT+9 on 1912-01-01? Omit the 1910 change for now.
+# (Another source "1987: Law No. 3919 (1986-12-31)" was in the 2014-10-30
+# edition of the Korean Wikipedia entry.)
#
# I guessed that time zone abbreviations through 1945 followed the same
# rules as discussed under Taiwan, with nominal switches from JST to KST
# when the respective cities were taken over by the Allies after WWII.
#
-# For Pyongyang we have no information; guess no changes since World War II.
+# For Pyongyang, guess no changes from World War II until 2015, as we
+# have no information otherwise.
# From Steffen Thorsen (2015-08-07):
# According to many news sources, North Korea is going to change to
@@ -2069,7 +2077,7 @@ Zone Indian/Maldives 4:54:00 - LMT 1880 # Male
# Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
# there is only one time zone and that DST is observed, citing Microsoft
# Windows XP as the source. Risto Nykänen (2005-05-16) reports that
-# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
+# travelmongolia.org says there are two time zones (UT +07, +08) with no DST.
# Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
# Washington, DC says there are two time zones, with DST observed.
# He also found
@@ -2572,11 +2580,6 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# From Paul Eggert (2015-03-03):
# http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014
# says that the fall 2014 transition was Oct 23 at 24:00.
-# For future dates, guess the last Friday in March at 24:00 through
-# the first Friday on or after October 21 at 00:00. This is consistent with
-# the predictions in today's editions of the following URLs:
-# http://www.timeanddate.com/time/change/gaza-strip/gaza
-# http://www.timeanddate.com/time/change/west-bank/hebron
# From Hannah Kreitem (2016-03-09):
# http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728
@@ -2586,7 +2589,21 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
#
# From Paul Eggert (2016-03-12):
# Predict spring transitions on March's last Saturday at 01:00 from now on.
-# Leave fall predictions alone for now.
+
+# From Sharef Mustafa (2016-10-19):
+# [T]he Palestinian cabinet decision (Mar 8th 2016) published on
+# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf
+# states that summer time will end on Oct 29th at 01:00.
+#
+# From Tim Parenti (2016-10-19):
+# Predict fall transitions on October's last Saturday at 01:00 from now on.
+# This is consistent with the 2016 transition as well as our spring
+# predictions.
+#
+# From Paul Eggert (2016-10-19):
+# It's also consistent with predictions in the following URLs today:
+# http://www.timeanddate.com/time/change/gaza-strip/gaza
+# http://www.timeanddate.com/time/change/west-bank/hebron
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
@@ -2615,9 +2632,10 @@ Rule Palestine 2011 only - Sep 30 0:00 0 -
Rule Palestine 2012 2014 - Mar lastThu 24:00 1:00 S
Rule Palestine 2012 only - Sep 21 1:00 0 -
Rule Palestine 2013 only - Sep Fri>=21 0:00 0 -
-Rule Palestine 2014 max - Oct Fri>=21 0:00 0 -
+Rule Palestine 2014 2015 - Oct Fri>=21 0:00 0 -
Rule Palestine 2015 only - Mar lastFri 24:00 1:00 S
Rule Palestine 2016 max - Mar lastSat 1:00 1:00 S
+Rule Palestine 2016 max - Oct lastSat 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@@ -2705,7 +2723,7 @@ Link Asia/Qatar Asia/Bahrain
# earlier date.
#
# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
-# time zones; the other zone, at UTC+4, was in the far eastern part of
+# time zones; the other zone, at UT +04, was in the far eastern part of
# the country. Ignore this, as it's before our 1970 cutoff.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -2767,45 +2785,31 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
# People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
# as that zone has agreed with the Tamil areas since our cutoff date of 1970.
-# From K Sethu (2006-04-25):
-# I think the abbreviation LKT originated from the world of computers at
-# the time of or subsequent to the time zone changes by SL Government
-# twice in 1996 and probably SL Government or its standardization
-# agencies never declared an abbreviation as a national standard.
-#
-# I recollect before the recent change the government announcements
-# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
-# Time and no mention was made about the abbreviation.
-#
-# If we look at Sri Lanka Department of Government's "Official News
-# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
-# use SLT as abbreviation in time stamp at the beginning of each news
-# item....
-#
-# Within Sri Lanka I think LKT is well known among computer users and
-# administrators. In my opinion SLT may not be a good choice because the
-# nation's largest telcom / internet operator Sri Lanka Telcom is well
-# known by that abbreviation - simply as SLT (there IP domains are
-# slt.lk and sltnet.lk).
-#
-# But if indeed our government has adopted SLT as standard abbreviation
-# (that we have not known so far) then it is better that it be used for
-# all computers.
-
-# From Paul Eggert (2006-04-25):
-# One possibility is that we wait for a bit for the dust to settle down
-# and then see what people actually say in practice.
+# From Sadika Sumanapala (2016-10-19):
+# According to http://www.sltime.org (maintained by Measurement Units,
+# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka
+# standard time is SLST.
+#
+# From Paul Eggert (2016-10-18):
+# "SLST" seems to be reasonably recent and rarely-used outside time
+# zone nerd sources. I searched Google News and found three uses of
+# it in the International Business Times of India in February and
+# March of this year when discussing cricket match times, but nothing
+# since then (though there has been a lot of cricket) and nothing in
+# other English-language news sources. Our old abbreviation "LKT" is
+# even worse. For now, let's use a numeric abbreviation; we can
+# switch to "SLST" if it catches on.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Colombo 5:19:24 - LMT 1880
5:19:32 - MMT 1906 # Moratuwa Mean Time
- 5:30 - IST 1942 Jan 5
- 5:30 0:30 IHST 1942 Sep
- 5:30 1:00 IST 1945 Oct 16 2:00
- 5:30 - IST 1996 May 25 0:00
- 6:30 - LKT 1996 Oct 26 0:30
- 6:00 - LKT 2006 Apr 15 0:30
- 5:30 - IST
+ 5:30 - +0530 1942 Jan 5
+ 5:30 0:30 +0530/+06 1942 Sep
+ 5:30 1:00 +0530/+0630 1945 Oct 16 2:00
+ 5:30 - +0530 1996 May 25 0:00
+ 6:30 - +0630 1996 Oct 26 0:30
+ 6:00 - +06 2006 Apr 15 0:30
+ 5:30 - +0530
# Syria
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -2974,10 +2978,10 @@ Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
# From Shanks & Pottenger.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2
- 5:00 - DUST 1930 Jun 21 # Dushanbe Time
- 6:00 RussiaAsia DUS%sT 1991 Mar 31 2:00s
- 5:00 1:00 DUSST 1991 Sep 9 2:00s
- 5:00 - TJT # Tajikistan Time
+ 5:00 - +05 1930 Jun 21
+ 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s
+ 5:00 1:00 +05/+06 1991 Sep 9 2:00s
+ 5:00 - +05
# Thailand
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -2991,11 +2995,10 @@ Link Asia/Bangkok Asia/Vientiane # Laos
# From Shanks & Pottenger.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad
- 4:00 - ASHT 1930 Jun 21 # Ashkhabad Time
- 5:00 RussiaAsia ASH%sT 1991 Mar 31 2:00
- 4:00 RussiaAsia ASH%sT 1991 Oct 27 # independence
- 4:00 RussiaAsia TM%sT 1992 Jan 19 2:00
- 5:00 - TMT
+ 4:00 - +04 1930 Jun 21
+ 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00
+ 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00
+ 5:00 - +05
# United Arab Emirates
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -3007,20 +3010,18 @@ Link Asia/Dubai Asia/Muscat # Oman
# Byalokoz 1919 says Uzbekistan was 4:27:53.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Samarkand 4:27:53 - LMT 1924 May 2
- 4:00 - SAMT 1930 Jun 21 # Samarkand Time
- 5:00 - SAMT 1981 Apr 1
- 5:00 1:00 SAMST 1981 Oct 1
- 6:00 - TAST 1982 Apr 1 # Tashkent Time
- 5:00 RussiaAsia SAM%sT 1991 Sep 1 # independence
- 5:00 RussiaAsia UZ%sT 1992
- 5:00 - UZT
+ 4:00 - +04 1930 Jun 21
+ 5:00 - +05 1981 Apr 1
+ 5:00 1:00 +06 1981 Oct 1
+ 6:00 - +06 1982 Apr 1
+ 5:00 RussiaAsia +05/+06 1992
+ 5:00 - +05
# Milne says Tashkent was 4:37:10.8; round to nearest.
Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2
- 5:00 - TAST 1930 Jun 21 # Tashkent Time
- 6:00 RussiaAsia TAS%sT 1991 Mar 31 2:00
- 5:00 RussiaAsia TAS%sT 1991 Sep 1 # independence
- 5:00 RussiaAsia UZ%sT 1992
- 5:00 - UZT
+ 5:00 - +05 1930 Jun 21
+ 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00
+ 5:00 RussiaAsia +05/+06 1992
+ 5:00 - +05
# Vietnam
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/australasia b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/australasia
index 134a01e..81ef521 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/australasia
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/australasia
@@ -373,7 +373,13 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# commencing at 2.00 am on Sunday 1st November, 2015 and ending at
# 3.00 am on Sunday 17th January, 2016.
-# From Paul Eggert (2015-09-01):
+# From Raymond Kumar (2016-10-04):
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx
+# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when
+# clocks go forward an hour at 2am to 3am.... Daylight Saving will
+# end at 3.00am on Sunday 15th January 2017."
+
+# From Paul Eggert (2016-10-03):
# For now, guess DST from 02:00 the first Sunday in November to
# 03:00 the third Sunday in January. Although ad hoc, it matches
# transitions since late 2014 and seems more likely to match future
@@ -568,7 +574,7 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
# Base the Bougainville entry on the Arawa-Kieta region, which appears to have
# the most people even though it was devastated in the Bougainville Civil War.
#
-# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates
+# Although Shanks gives 1942-03-15 / 1943-11-01 for UT +09, these dates
# are apparently rough guesswork from the starts of military campaigns.
# The World War II entries below are instead based on Arawa-Kieta.
# The Japanese occupied Kieta in July 1942,
@@ -576,8 +582,8 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
# http://pwencycl.kgbudge.com/B/o/Bougainville.htm
# and seem to have controlled it until their 1945-08-21 surrender.
#
-# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11
-# on 2014-12-28 at 02:00. They call UTC+11 "Bougainville Standard Time";
+# The Autonomous Region of Bougainville switched from UT +10 to +11
+# on 2014-12-28 at 02:00. They call +11 "Bougainville Standard Time";
# abbreviate this as BST. See:
# http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/
#
@@ -643,7 +649,7 @@ Link Pacific/Pago_Pago Pacific/Midway # in US minor outlying islands
# From Paul Eggert (2014-06-27):
# The International Date Line Act 2011
# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
-# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# changed Samoa from UT -11 to +13, effective "12 o'clock midnight, on
# Thursday 29th December 2011". The International Date Line was adjusted
# accordingly.
@@ -719,11 +725,13 @@ Rule Tonga 1999 only - Oct 7 2:00s 1:00 S
Rule Tonga 2000 only - Mar 19 2:00s 0 -
Rule Tonga 2000 2001 - Nov Sun>=1 2:00 1:00 S
Rule Tonga 2001 2002 - Jan lastSun 2:00 0 -
+Rule Tonga 2016 max - Nov Sun>=1 2:00 1:00 S
+Rule Tonga 2017 max - Jan Sun>=15 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Tongatapu 12:19:20 - LMT 1901
- 12:20 - TOT 1941 # Tonga Time
- 13:00 - TOT 1999
- 13:00 Tonga TO%sT
+ 12:20 - +1220 1941
+ 13:00 - +13 1999
+ 13:00 Tonga +13/+14
# Tuvalu
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -738,7 +746,7 @@ Zone Pacific/Funafuti 11:56:52 - LMT 1901
# 1886-1891; Baker was similar but exact dates are not known.
# Inhabited by civilians 1935-1942; U.S. military bases 1943-1944;
# uninhabited thereafter.
-# Howland observed Hawaii Standard Time (UT-10:30) in 1937;
+# Howland observed Hawaii Standard Time (UT -10:30) in 1937;
# see page 206 of Elgen M. Long and Marie K. Long,
# Amelia Earhart: the Mystery Solved, Simon & Schuster (2000).
# So most likely Howland and Baker observed Hawaii Time from 1935
@@ -1496,7 +1504,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# Zealand time. I understand that is the time they keep locally, anyhow."
# For now, assume this practice goes back to the introduction of standard time
# in New Zealand, as this would make Chatham Islands time almost exactly match
-# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# LMT back when New Zealand was at UT +11:30; also, assume Chatham Islands did
# not observe New Zealand's prewar DST.
###############################################################################
@@ -1552,7 +1560,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# For now, we assume the Ladrones switched at the same time as the Philippines;
# see Asia/Manila.
-# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time,
+# US Public Law 106-564 (2000-12-23) made UT +10 the official standard time,
# under the name "Chamorro Standard Time". There is no official abbreviation,
# but Congressman Robert A. Underwood, author of the bill that became law,
# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
@@ -1564,15 +1572,15 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# "I am certain, having lived there for the past decade, that 'Truk'
# (now properly known as Chuuk) ... is in the time zone GMT+10."
#
-# Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
+# Shanks & Pottenger write that Truk switched from UT +10 to +11
# on 1978-10-01; ignore this for now.
# From Paul Eggert (1999-10-29):
# The Federated States of Micronesia Visitors Board writes in
# The Federated States of Micronesia - Visitor Information (1999-01-26)
# http://www.fsmgov.org/info/clocks.html
-# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
-# We don't know when Kosrae switched from UTC+12; assume January 1 for now.
+# that Truk and Yap are UT +10, and Ponape and Kosrae are +11.
+# We don't know when Kosrae switched from +12; assume January 1 for now.
# Midway
@@ -1638,11 +1646,11 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# ordaining - by a masterpiece of diplomatic flattery - that
# the Fourth of July should be celebrated twice in that year."
-# Although Shanks & Pottenger says they both switched to UTC-11:30
-# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# Although Shanks & Pottenger says they both switched to UT -11:30
+# in 1911, and to -11 in 1950. many earlier sources give -11
# for American Samoa, e.g., the US National Bureau of Standards
# circular "Standard Time Throughout the World", 1932.
-# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# Assume American Samoa switched to -11 in 1911, not 1950,
# and that after 1950 they agreed until (western) Samoa skipped a
# day in 2011. Assume also that the Samoas follow the US and New
# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
@@ -1729,9 +1737,17 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# of January the standard time in the Kingdom shall be moved backward by one
# hour to 1:00am.
-# From Pulu 'Anau (2002-11-05):
+# From Pulu ʻAnau (2002-11-05):
# The law was for 3 years, supposedly to get renewed. It wasn't.
+# From Pulu ʻAnau (2016-10-27):
+# http://mic.gov.to/news-today/press-releases/6375-daylight-saving-set-to-run-from-6-november-2016-to-15-january-2017
+# Cannot find anyone who knows the rules, has seen the duration or has seen
+# the cabinet decision, but it appears we are following Fiji's rule set.
+#
+# From Tim Parenti (2016-10-26):
+# Assume Tonga will observe DST from the first Sunday in November at 02:00
+# through the third Sunday in January at 03:00, like Fiji, for now.
# Wake
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/backward b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/backward
index 8352705..ec96c7e 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/backward
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/backward
@@ -59,6 +59,7 @@ Link Asia/Shanghai Asia/Harbin
Link Asia/Urumqi Asia/Kashgar
Link Asia/Kathmandu Asia/Katmandu
Link Asia/Macau Asia/Macao
+Link Asia/Yangon Asia/Rangoon
Link Asia/Ho_Chi_Minh Asia/Saigon
Link Asia/Jerusalem Asia/Tel_Aviv
Link Asia/Thimphu Asia/Thimbu
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/etcetera b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/etcetera
index d2fb91c..ec31f1b 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/etcetera
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/etcetera
@@ -31,6 +31,13 @@
# need now for the entries that are not on UTC are for ships at sea
# that cannot use POSIX TZ settings.
+# Starting with POSIX 1003.1-2001, the entries below are all
+# unnecessary as settings for the TZ environment variable. E.g.,
+# instead of TZ='Etc/GMT+4' one can use the POSIX setting TZ='<-04>+4'.
+#
+# Do not use a POSIX TZ setting like TZ='GMT+4', which is four hours
+# behind GMT but uses the completely misleading abbreviation "GMT".
+
Zone Etc/GMT 0 - GMT
Zone Etc/UTC 0 - UTC
Zone Etc/UCT 0 - UCT
@@ -49,23 +56,13 @@ Link Etc/GMT Etc/GMT-0
Link Etc/GMT Etc/GMT+0
Link Etc/GMT Etc/GMT0
-# We use POSIX-style signs in the Zone names and the output abbreviations,
+# Be consistent with POSIX TZ settings in the Zone names,
# even though this is the opposite of what many people expect.
# POSIX has positive signs west of Greenwich, but many people expect
# positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses
-# the abbreviation "GMT+4" and corresponds to 4 hours behind UT
+# the abbreviation "-04" and corresponds to 4 hours behind UT
# (i.e. west of Greenwich) even though many people would expect it to
# mean 4 hours ahead of UT (i.e. east of Greenwich).
-#
-# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for
-# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to
-# ISO 8601 you can use TZ='<-0400>+4'. Thus the commonly-expected
-# offset is kept within the angle bracket (and is used for display)
-# while the POSIX sign is kept outside the angle bracket (and is used
-# for calculation).
-#
-# Do not use a TZ setting like TZ='GMT+4', which is four hours behind
-# GMT but uses the completely misleading abbreviation "GMT".
# Earlier incarnations of this package were not POSIX-compliant,
# and had lines such as
@@ -74,30 +71,31 @@ Link Etc/GMT Etc/GMT0
# way does a
# zic -l GMT-12
# so we moved the names into the Etc subdirectory.
+# Also, the time zone abbreviations are now compatible with %z.
-Zone Etc/GMT-14 14 - GMT-14 # 14 hours ahead of GMT
-Zone Etc/GMT-13 13 - GMT-13
-Zone Etc/GMT-12 12 - GMT-12
-Zone Etc/GMT-11 11 - GMT-11
-Zone Etc/GMT-10 10 - GMT-10
-Zone Etc/GMT-9 9 - GMT-9
-Zone Etc/GMT-8 8 - GMT-8
-Zone Etc/GMT-7 7 - GMT-7
-Zone Etc/GMT-6 6 - GMT-6
-Zone Etc/GMT-5 5 - GMT-5
-Zone Etc/GMT-4 4 - GMT-4
-Zone Etc/GMT-3 3 - GMT-3
-Zone Etc/GMT-2 2 - GMT-2
-Zone Etc/GMT-1 1 - GMT-1
-Zone Etc/GMT+1 -1 - GMT+1
-Zone Etc/GMT+2 -2 - GMT+2
-Zone Etc/GMT+3 -3 - GMT+3
-Zone Etc/GMT+4 -4 - GMT+4
-Zone Etc/GMT+5 -5 - GMT+5
-Zone Etc/GMT+6 -6 - GMT+6
-Zone Etc/GMT+7 -7 - GMT+7
-Zone Etc/GMT+8 -8 - GMT+8
-Zone Etc/GMT+9 -9 - GMT+9
-Zone Etc/GMT+10 -10 - GMT+10
-Zone Etc/GMT+11 -11 - GMT+11
-Zone Etc/GMT+12 -12 - GMT+12
+Zone Etc/GMT-14 14 - +14
+Zone Etc/GMT-13 13 - +13
+Zone Etc/GMT-12 12 - +12
+Zone Etc/GMT-11 11 - +11
+Zone Etc/GMT-10 10 - +10
+Zone Etc/GMT-9 9 - +09
+Zone Etc/GMT-8 8 - +08
+Zone Etc/GMT-7 7 - +07
+Zone Etc/GMT-6 6 - +06
+Zone Etc/GMT-5 5 - +05
+Zone Etc/GMT-4 4 - +04
+Zone Etc/GMT-3 3 - +03
+Zone Etc/GMT-2 2 - +02
+Zone Etc/GMT-1 1 - +01
+Zone Etc/GMT+1 -1 - -01
+Zone Etc/GMT+2 -2 - -02
+Zone Etc/GMT+3 -3 - -03
+Zone Etc/GMT+4 -4 - -04
+Zone Etc/GMT+5 -5 - -05
+Zone Etc/GMT+6 -6 - -06
+Zone Etc/GMT+7 -7 - -07
+Zone Etc/GMT+8 -8 - -08
+Zone Etc/GMT+9 -9 - -09
+Zone Etc/GMT+10 -10 - -10
+Zone Etc/GMT+11 -11 - -11
+Zone Etc/GMT+12 -12 - -12
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/europe b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/europe
index 8ed7d4b..df46485 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/europe
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/europe
@@ -98,8 +98,7 @@
# 1:00 CET CEST CEMT Central Europe
# 1:00:14 SET Swedish (1879-1899)*
# 2:00 EET EEST Eastern Europe
-# 3:00 FET Further-eastern Europe (2011-2014)*
-# 3:00 MSK MSD MSM* Minsk, Moscow
+# 3:00 MSK MSD Moscow
# From Peter Ilieve (1994-12-04),
# The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -606,16 +605,33 @@ Rule E-Eur 1979 1995 - Sep lastSun 0:00 0 -
Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S
Rule E-Eur 1996 max - Oct lastSun 0:00 0 -
+
+# Daylight saving time for Russia and the Soviet Union
+#
+# The 1917-1921 decree URLs are from Alexander Belopolsky (2016-08-23).
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Russia 1917 only - Jul 1 23:00 1:00 MST # Moscow Summer Time
+#
+# Decree No. 142 (1917-12-22) http://istmat.info/node/28137
Rule Russia 1917 only - Dec 28 0:00 0 MMT # Moscow Mean Time
+#
+# Decree No. 497 (1918-05-30) http://istmat.info/node/30001
Rule Russia 1918 only - May 31 22:00 2:00 MDST # Moscow Double Summer Time
Rule Russia 1918 only - Sep 16 1:00 1:00 MST
+#
+# Decree No. 258 (1919-05-29) http://istmat.info/node/37949
Rule Russia 1919 only - May 31 23:00 2:00 MDST
-Rule Russia 1919 only - Jul 1 2:00 1:00 MSD
+#
+Rule Russia 1919 only - Jul 1 0:00u 1:00 MSD
Rule Russia 1919 only - Aug 16 0:00 0 MSK
+#
+# Decree No. 63 (1921-02-03) http://istmat.info/node/45840
Rule Russia 1921 only - Feb 14 23:00 1:00 MSD
-Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer
+#
+# Decree No. 121 (1921-03-07) http://istmat.info/node/45949
+Rule Russia 1921 only - Mar 20 23:00 2:00 +05
+#
Rule Russia 1921 only - Sep 1 0:00 1:00 MSD
Rule Russia 1921 only - Oct 1 0:00 0 -
# Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
@@ -798,8 +814,6 @@ Zone Europe/Vienna 1:05:21 - LMT 1893 Apr
# From Alexander Bokovoy (2014-10-09):
# Belarussian government decided against changing to winter time....
# http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html
-# From Paul Eggert (2014-10-08):
-# Hence Belarus can share time zone abbreviations with Moscow again.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Minsk 1:50:16 - LMT 1880
@@ -810,8 +824,7 @@ Zone Europe/Minsk 1:50:16 - LMT 1880
3:00 Russia MSK/MSD 1990
3:00 - MSK 1991 Mar 31 2:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
- 3:00 - FET 2014 Oct 26 1:00s
- 3:00 - MSK
+ 3:00 - +03
# Belgium
#
@@ -1319,7 +1332,7 @@ Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15 0:01
# http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
# says that Bersarin issued an order to use Moscow time on May 20.
# However, Moscow did not observe daylight saving in 1945, so
-# this was equivalent to CEMT (GMT+3), not GMT+4.
+# this was equivalent to UT +03, not +04.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -1510,73 +1523,84 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908
# But these events all occurred before the 1970 cutoff,
# so record only the time in Rome.
#
-# From Paul Eggert (2006-03-22):
-# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
-# F. Pollastri
-# Day-light Saving Time in Italy (2006-02-03)
-# http://toi.iriti.cnr.it/uk/ienitlt.html
-# ('FP' below), taken from an Italian National Electrotechnical Institute
-# publication. When the three sources disagree, guess who's right, as follows:
-#
-# year FP Shanks&P. (S) Whitman (W) Go with:
-# 1916 06-03 06-03 24:00 06-03 00:00 FP & W
-# 09-30 09-30 24:00 09-30 01:00 FP; guess 24:00s
-# 1917 04-01 03-31 24:00 03-31 00:00 FP & S
-# 09-30 09-29 24:00 09-30 01:00 FP & W
-# 1918 03-09 03-09 24:00 03-09 00:00 FP & S
-# 10-06 10-05 24:00 10-06 01:00 FP & W
-# 1919 03-01 03-01 24:00 03-01 00:00 FP & S
-# 10-04 10-04 24:00 10-04 01:00 FP; guess 24:00s
-# 1920 03-20 03-20 24:00 03-20 00:00 FP & S
-# 09-18 09-18 24:00 10-01 01:00 FP; guess 24:00s
-# 1944 04-02 04-03 02:00 S (see C-Eur)
-# 09-16 10-02 03:00 FP; guess 24:00s
-# 1945 09-14 09-16 24:00 FP; guess 24:00s
-# 1970 05-21 05-31 00:00 S
-# 09-20 09-27 00:00 S
+# From Michael Deckers (2016-10-24):
+# http://www.ac-ilsestante.it/MERIDIANE/ora_legale quotes a law of 1893-08-10
+# ... [translated as] "The preceding dispositions will enter into
+# force at the instant at which, according to the time specified in
+# the 1st article, the 1st of November 1893 will begin...."
+#
+# From Pierpaolo Bernardi (2016-10-20):
+# The authoritative source for time in Italy is the national metrological
+# institute, which has a summary page of historical DST data at
+# http://www.inrim.it/res/tf/ora_legale_i.shtml
+# (2016-10-24):
+# http://www.renzobaldini.it/le-ore-legali-in-italia/
+# has still different data for 1944. It divides Italy in two, as
+# there were effectively two governments at the time, north of Gothic
+# Line German controlled territory, official government RSI, and south
+# of the Gothic Line, controlled by allied armies.
+#
+# From Brian Inglis (2016-10-23):
+# Viceregal LEGISLATIVE DECREE. 14 September 1944, no. 219.
+# Restoration of Standard Time. (044U0219) (OJ 62 of 30.9.1944) ...
+# Given the R. law decreed on 1944-03-29, no. 92, by which standard time is
+# advanced to sixty minutes later starting at hour two on 1944-04-02; ...
+# Starting at hour three on the date 1944-09-17 standard time will be resumed.
+#
+# From Paul Eggert (2016-10-27):
+# Go with INRiM for DST rules, except as corrected by Inglis for 1944
+# for the Kingdom of Italy. This is consistent with Renzo Baldini.
+# Model Rome's occupation by using using C-Eur rules from 1943-09-10
+# to 1944-06-04; although Rome was an open city during this period, it
+# was effectively controlled by Germany.
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Italy 1916 only - Jun 3 0:00s 1:00 S
-Rule Italy 1916 only - Oct 1 0:00s 0 -
-Rule Italy 1917 only - Apr 1 0:00s 1:00 S
-Rule Italy 1917 only - Sep 30 0:00s 0 -
-Rule Italy 1918 only - Mar 10 0:00s 1:00 S
-Rule Italy 1918 1919 - Oct Sun>=1 0:00s 0 -
-Rule Italy 1919 only - Mar 2 0:00s 1:00 S
-Rule Italy 1920 only - Mar 21 0:00s 1:00 S
-Rule Italy 1920 only - Sep 19 0:00s 0 -
-Rule Italy 1940 only - Jun 15 0:00s 1:00 S
-Rule Italy 1944 only - Sep 17 0:00s 0 -
-Rule Italy 1945 only - Apr 2 2:00 1:00 S
-Rule Italy 1945 only - Sep 15 0:00s 0 -
-Rule Italy 1946 only - Mar 17 2:00s 1:00 S
-Rule Italy 1946 only - Oct 6 2:00s 0 -
-Rule Italy 1947 only - Mar 16 0:00s 1:00 S
-Rule Italy 1947 only - Oct 5 0:00s 0 -
-Rule Italy 1948 only - Feb 29 2:00s 1:00 S
-Rule Italy 1948 only - Oct 3 2:00s 0 -
-Rule Italy 1966 1968 - May Sun>=22 0:00 1:00 S
-Rule Italy 1966 1969 - Sep Sun>=22 0:00 0 -
-Rule Italy 1969 only - Jun 1 0:00 1:00 S
-Rule Italy 1970 only - May 31 0:00 1:00 S
-Rule Italy 1970 only - Sep lastSun 0:00 0 -
-Rule Italy 1971 1972 - May Sun>=22 0:00 1:00 S
-Rule Italy 1971 only - Sep lastSun 1:00 0 -
-Rule Italy 1972 only - Oct 1 0:00 0 -
-Rule Italy 1973 only - Jun 3 0:00 1:00 S
-Rule Italy 1973 1974 - Sep lastSun 0:00 0 -
-Rule Italy 1974 only - May 26 0:00 1:00 S
-Rule Italy 1975 only - Jun 1 0:00s 1:00 S
-Rule Italy 1975 1977 - Sep lastSun 0:00s 0 -
-Rule Italy 1976 only - May 30 0:00s 1:00 S
-Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 S
-Rule Italy 1978 only - Oct 1 0:00s 0 -
-Rule Italy 1979 only - Sep 30 0:00s 0 -
+Rule Italy 1916 only - Jun 3 24:00 1:00 S
+Rule Italy 1916 1917 - Sep 30 24:00 0 -
+Rule Italy 1917 only - Mar 31 24:00 1:00 S
+Rule Italy 1918 only - Mar 9 24:00 1:00 S
+Rule Italy 1918 only - Oct 6 24:00 0 -
+Rule Italy 1919 only - Mar 1 24:00 1:00 S
+Rule Italy 1919 only - Oct 4 24:00 0 -
+Rule Italy 1920 only - Mar 20 24:00 1:00 S
+Rule Italy 1920 only - Sep 18 24:00 0 -
+Rule Italy 1940 only - Jun 14 24:00 1:00 S
+Rule Italy 1942 only - Nov 2 2:00s 0 -
+Rule Italy 1943 only - Mar 29 2:00s 1:00 S
+Rule Italy 1943 only - Oct 4 2:00s 0 -
+Rule Italy 1944 only - Apr 2 2:00s 1:00 S
+Rule Italy 1944 only - Sep 17 2:00s 0 -
+Rule Italy 1945 only - Apr 2 2:00 1:00 S
+Rule Italy 1945 only - Sep 15 1:00 0 -
+Rule Italy 1946 only - Mar 17 2:00s 1:00 S
+Rule Italy 1946 only - Oct 6 2:00s 0 -
+Rule Italy 1947 only - Mar 16 0:00s 1:00 S
+Rule Italy 1947 only - Oct 5 0:00s 0 -
+Rule Italy 1948 only - Feb 29 2:00s 1:00 S
+Rule Italy 1948 only - Oct 3 2:00s 0 -
+Rule Italy 1966 1968 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1966 only - Sep 24 24:00 0 -
+Rule Italy 1967 1969 - Sep Sun>=22 0:00s 0 -
+Rule Italy 1969 only - Jun 1 0:00s 1:00 S
+Rule Italy 1970 only - May 31 0:00s 1:00 S
+Rule Italy 1970 only - Sep lastSun 0:00s 0 -
+Rule Italy 1971 1972 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1971 only - Sep lastSun 0:00s 0 -
+Rule Italy 1972 only - Oct 1 0:00s 0 -
+Rule Italy 1973 only - Jun 3 0:00s 1:00 S
+Rule Italy 1973 1974 - Sep lastSun 0:00s 0 -
+Rule Italy 1974 only - May 26 0:00s 1:00 S
+Rule Italy 1975 only - Jun 1 0:00s 1:00 S
+Rule Italy 1975 1977 - Sep lastSun 0:00s 0 -
+Rule Italy 1976 only - May 30 0:00s 1:00 S
+Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 S
+Rule Italy 1978 only - Oct 1 0:00s 0 -
+Rule Italy 1979 only - Sep 30 0:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Rome 0:49:56 - LMT 1866 Sep 22
- 0:49:56 - RMT 1893 Nov 1 0:00s # Rome Mean
- 1:00 Italy CE%sT 1942 Nov 2 2:00s
- 1:00 C-Eur CE%sT 1944 Jul
+ 0:49:56 - RMT 1893 Oct 31 23:49:56 # Rome Mean
+ 1:00 Italy CE%sT 1943 Sep 10
+ 1:00 C-Eur CE%sT 1944 Jun 4
1:00 Italy CE%sT 1980
1:00 EU CE%sT
@@ -1775,6 +1799,10 @@ Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
# See Europe/Belgrade.
# Malta
+#
+# From Paul Eggert (2016-10-21):
+# Assume 1900-1972 was like Rome, overriding Shanks.
+#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Malta 1973 only - Mar 31 0:00s 1:00 S
Rule Malta 1973 only - Sep 29 0:00s 0 -
@@ -1785,8 +1813,6 @@ Rule Malta 1975 1980 - Sep Sun>=15 2:00 0 -
Rule Malta 1980 only - Mar 31 2:00 1:00 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta
- 1:00 Italy CE%sT 1942 Nov 2 2:00s
- 1:00 C-Eur CE%sT 1945 Apr 2 2:00s
1:00 Italy CE%sT 1973 Mar 31
1:00 Malta CE%sT 1981
1:00 EU CE%sT
@@ -1918,7 +1944,7 @@ Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
# Amsterdam mean time.
# The data entries before 1945 are taken from
-# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
+# http://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time
@@ -2283,7 +2309,6 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
# From Paul Eggert (2006-03-22):
-# Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
# Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
# are from Andrey A. Chernov. The rest is from Shanks & Pottenger,
# except we follow Chernov's report that 1992 DST transitions were Sat
@@ -2359,7 +2384,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
2:00 Poland CE%sT 1946
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
- 3:00 - FET 2014 Oct 26 2:00s
+ 3:00 - +03 2014 Oct 26 2:00s
2:00 - EET
@@ -2412,6 +2437,16 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
# 78 RU-SPE Saint Petersburg
# 83 RU-NEN Nenets Autonomous Okrug
+# From Paul Eggert (2016-08-23):
+# The Soviets switched to UT-based time in 1919. Decree No. 59
+# (1919-02-08) http://istmat.info/node/35567 established UT-based time
+# zones, and Decree No. 147 (1919-03-29) http://istmat.info/node/35854
+# specified a transition date of 1919-07-01, apparently at 00:00 UT.
+# No doubt only the Soviet-controlled regions switched on that date;
+# later transitions to UT-based time in other parts of Russia are
+# taken from what appear to be guesses by Shanks.
+# (Thanks to Alexander Belopolsky for pointers to the decrees.)
+
# From Stepan Golosunov (2016-03-07):
# 11. Regions-violators, 1981-1982.
# Wikipedia refers to
@@ -2453,7 +2488,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
# attributes the 1982 changes to the Act of the Council of Ministers
# of the USSR No. 126 from 18.02.1982. 1980-925.txt also adds
# Udmurtia to the list of affected territories and lists Khatangsky
-# district separately from Taymyr Autonomous Okurg. Probably erroneously.
+# district separately from Taymyr Autonomous Okrug. Probably erroneously.
#
# The affected territories are currently listed under Europe/Moscow,
# Asia/Yekaterinburg and Asia/Krasnoyarsk.
@@ -2513,7 +2548,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
Zone Europe/Moscow 2:30:17 - LMT 1880
2:30:17 - MMT 1916 Jul 3 # Moscow Mean Time
- 2:31:19 Russia %s 1919 Jul 1 2:00
+ 2:31:19 Russia %s 1919 Jul 1 0:00u
3:00 Russia %s 1921 Oct
3:00 Russia MSK/MSD 1922 Oct
2:00 - EET 1930 Jun 21
@@ -2596,22 +2631,21 @@ Zone Europe/Astrakhan 3:12:12 - LMT 1924 May
# The 1988 transition is from USSR act No. 5 (1988-01-04).
Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3
- 3:00 - TSAT 1925 Apr 6 # Tsaritsyn Time
- 3:00 - STAT 1930 Jun 21 # Stalingrad Time
- 4:00 - STAT 1961 Nov 11
- 4:00 Russia VOL%sT 1988 Mar 27 2:00s # Volgograd T
- 3:00 Russia VOL%sT 1991 Mar 31 2:00s
- 4:00 - VOLT 1992 Mar 29 2:00s
- 3:00 Russia MSK/MSD 2011 Mar 27 2:00s
- 4:00 - MSK 2014 Oct 26 2:00s
- 3:00 - MSK
+ 3:00 - +03 1930 Jun 21
+ 4:00 - +04 1961 Nov 11
+ 4:00 Russia +04/+05 1988 Mar 27 2:00s
+ 3:00 Russia +03/+04 1991 Mar 31 2:00s
+ 4:00 - +04 1992 Mar 29 2:00s
+ 3:00 Russia +03/+04 2011 Mar 27 2:00s
+ 4:00 - +04 2014 Oct 26 2:00s
+ 3:00 - +03
# From Paul Eggert (2016-03-18):
# Europe/Kirov covers:
# 43 RU-KIR Kirov Oblast
# The 1989 transition is from USSR act No. 227 (1989-03-14).
#
-Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 2:00
+Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0:00u
3:00 - +03 1930 Jun 21
4:00 Russia +04/+05 1989 Mar 26 2:00s
3:00 Russia +03/+04 1991 Mar 31 2:00s
@@ -2629,16 +2663,16 @@ Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 2:00
# Byalokoz 1919 says Samara was 3:20:20.
# The 1989 transition is from USSR act No. 227 (1989-03-14).
-Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 2:00
- 3:00 - SAMT 1930 Jun 21 # Samara Time
- 4:00 - SAMT 1935 Jan 27
- 4:00 Russia KUY%sT 1989 Mar 26 2:00s # Kuybyshev
- 3:00 Russia MSK/MSD 1991 Mar 31 2:00s
- 2:00 Russia EE%sT 1991 Sep 29 2:00s
- 3:00 - SAMT 1991 Oct 20 3:00
- 4:00 Russia SAM%sT 2010 Mar 28 2:00s
- 3:00 Russia SAM%sT 2011 Mar 27 2:00s
- 4:00 - SAMT
+Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 0:00u
+ 3:00 - +03 1930 Jun 21
+ 4:00 - +04 1935 Jan 27
+ 4:00 Russia +04/+05 1989 Mar 26 2:00s
+ 3:00 Russia +03/+04 1991 Mar 31 2:00s
+ 2:00 Russia +02/+03 1991 Sep 29 2:00s
+ 3:00 - +03 1991 Oct 20 3:00
+ 4:00 Russia +04/+05 2010 Mar 28 2:00s
+ 3:00 Russia +03/+04 2011 Mar 27 2:00s
+ 4:00 - +04
# From Paul Eggert (2016-03-18):
# Europe/Ulyanovsk covers:
@@ -2653,7 +2687,7 @@ Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 2:00
# From Matt Johnson (2016-03-09):
# http://publication.pravo.gov.ru/Document/View/0001201603090051
-Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 2:00
+Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0:00u
3:00 - +03 1930 Jun 21
4:00 Russia +04/+05 1989 Mar 26 2:00s
3:00 Russia +03/+04 1991 Mar 31 2:00s
@@ -2685,12 +2719,12 @@ Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 2:00
Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3
3:45:05 - PMT 1919 Jul 15 4:00
- 4:00 - SVET 1930 Jun 21 # Sverdlovsk Time
- 5:00 Russia SVE%sT 1991 Mar 31 2:00s
- 4:00 Russia SVE%sT 1992 Jan 19 2:00s
- 5:00 Russia YEK%sT 2011 Mar 27 2:00s
- 6:00 - YEKT 2014 Oct 26 2:00s
- 5:00 - YEKT
+ 4:00 - +04 1930 Jun 21
+ 5:00 Russia +05/+06 1991 Mar 31 2:00s
+ 4:00 Russia +04/+05 1992 Jan 19 2:00s
+ 5:00 Russia +05/+06 2011 Mar 27 2:00s
+ 6:00 - +06 2014 Oct 26 2:00s
+ 5:00 - +05
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -2700,12 +2734,12 @@ Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3
# Byalokoz 1919 says Omsk was 4:53:30.
Zone Asia/Omsk 4:53:30 - LMT 1919 Nov 14
- 5:00 - OMST 1930 Jun 21 # Omsk Time
- 6:00 Russia OMS%sT 1991 Mar 31 2:00s
- 5:00 Russia OMS%sT 1992 Jan 19 2:00s
- 6:00 Russia OMS%sT 2011 Mar 27 2:00s
- 7:00 - OMST 2014 Oct 26 2:00s
- 6:00 - OMST
+ 5:00 - +05 1930 Jun 21
+ 6:00 Russia +06/+07 1991 Mar 31 2:00s
+ 5:00 Russia +05/+06 1992 Jan 19 2:00s
+ 6:00 Russia +06/+07 2011 Mar 27 2:00s
+ 7:00 - +07 2014 Oct 26 2:00s
+ 6:00 - +06
# From Paul Eggert (2016-02-22):
# Asia/Barnaul covers:
@@ -2785,7 +2819,7 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
# Note that time belts (numbered from 2 (Moscow) to 12 according to their
# GMT/UTC offset and having too many exceptions like regions formally
# belonging to one belt but using time from another) were replaced
-# with time zones in 2011 with different numberings (there was a
+# with time zones in 2011 with different numbering (there was a
# 2-hour gap between second and third zones in 2011-2014).
# From Stepan Golosunov (2016-04-12):
@@ -2868,12 +2902,12 @@ Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1
# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6
- 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
- 7:00 Russia KRA%sT 1991 Mar 31 2:00s
- 6:00 Russia KRA%sT 1992 Jan 19 2:00s
- 7:00 Russia KRA%sT 2011 Mar 27 2:00s
- 8:00 - KRAT 2014 Oct 26 2:00s
- 7:00 - KRAT
+ 6:00 - +06 1930 Jun 21
+ 7:00 Russia +07/+08 1991 Mar 31 2:00s
+ 6:00 Russia +06/+07 1992 Jan 19 2:00s
+ 7:00 Russia +07/+08 2011 Mar 27 2:00s
+ 8:00 - +08 2014 Oct 26 2:00s
+ 7:00 - +07
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -2890,12 +2924,12 @@ Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6
Zone Asia/Irkutsk 6:57:05 - LMT 1880
6:57:05 - IMT 1920 Jan 25 # Irkutsk Mean Time
- 7:00 - IRKT 1930 Jun 21 # Irkutsk Time
- 8:00 Russia IRK%sT 1991 Mar 31 2:00s
- 7:00 Russia IRK%sT 1992 Jan 19 2:00s
- 8:00 Russia IRK%sT 2011 Mar 27 2:00s
- 9:00 - IRKT 2014 Oct 26 2:00s
- 8:00 - IRKT
+ 7:00 - +07 1930 Jun 21
+ 8:00 Russia +08/+09 1991 Mar 31 2:00s
+ 7:00 Russia +07/+08 1992 Jan 19 2:00s
+ 8:00 Russia +08/+09 2011 Mar 27 2:00s
+ 9:00 - +09 2014 Oct 26 2:00s
+ 8:00 - +08
# From Tim Parenti (2014-07-06):
@@ -2912,13 +2946,13 @@ Zone Asia/Irkutsk 6:57:05 - LMT 1880
# http://publication.pravo.gov.ru/Document/View/0001201512300107
Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAK%sT 1991 Mar 31 2:00s
- 8:00 Russia YAK%sT 1992 Jan 19 2:00s
- 9:00 Russia YAK%sT 2011 Mar 27 2:00s
- 10:00 - YAKT 2014 Oct 26 2:00s
- 8:00 - IRKT 2016 Mar 27 2:00
- 9:00 - YAKT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1991 Mar 31 2:00s
+ 8:00 Russia +08/+09 1992 Jan 19 2:00s
+ 9:00 Russia +09/+10 2011 Mar 27 2:00s
+ 10:00 - +10 2014 Oct 26 2:00s
+ 8:00 - +08 2016 Mar 27 2:00
+ 9:00 - +09
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -2958,12 +2992,12 @@ Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15
# Byalokoz 1919 says Yakutsk was 8:38:58.
Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAK%sT 1991 Mar 31 2:00s
- 8:00 Russia YAK%sT 1992 Jan 19 2:00s
- 9:00 Russia YAK%sT 2011 Mar 27 2:00s
- 10:00 - YAKT 2014 Oct 26 2:00s
- 9:00 - YAKT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1991 Mar 31 2:00s
+ 8:00 Russia +08/+09 1992 Jan 19 2:00s
+ 9:00 Russia +09/+10 2011 Mar 27 2:00s
+ 10:00 - +10 2014 Oct 26 2:00s
+ 9:00 - +09
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -2981,12 +3015,12 @@ Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15
# Go with Byalokoz.
Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15
- 9:00 - VLAT 1930 Jun 21 # Vladivostok Time
- 10:00 Russia VLA%sT 1991 Mar 31 2:00s
- 9:00 Russia VLA%sT 1992 Jan 19 2:00s
- 10:00 Russia VLA%sT 2011 Mar 27 2:00s
- 11:00 - VLAT 2014 Oct 26 2:00s
- 10:00 - VLAT
+ 9:00 - +09 1930 Jun 21
+ 10:00 Russia +10/+11 1991 Mar 31 2:00s
+ 9:00 Russia +09/+10 1992 Jan 19 2:00s
+ 10:00 Russia +10/+11 2011 Mar 27 2:00s
+ 11:00 - +11 2014 Oct 26 2:00s
+ 10:00 - +10
# From Tim Parenti (2014-07-03):
@@ -3004,14 +3038,14 @@ Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15
# This transition is no doubt wrong, but we have no better info.
Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAK%sT 1991 Mar 31 2:00s
- 8:00 Russia YAK%sT 1992 Jan 19 2:00s
- 9:00 Russia YAK%sT 2004
- 10:00 Russia VLA%sT 2011 Mar 27 2:00s
- 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725?
- 10:00 - YAKT 2014 Oct 26 2:00s
- 9:00 - YAKT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1991 Mar 31 2:00s
+ 8:00 Russia +08/+09 1992 Jan 19 2:00s
+ 9:00 Russia +09/+10 2004
+ 10:00 Russia +10/+11 2011 Mar 27 2:00s
+ 11:00 - +11 2011 Sep 13 0:00s # Decree 725?
+ 10:00 - +10 2014 Oct 26 2:00s
+ 9:00 - +09
# From Tim Parenti (2014-07-03):
@@ -3027,15 +3061,14 @@ Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15
# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
- 9:00 - JCST 1937 Oct 1
- 9:00 - JST 1945 Aug 25
- 11:00 Russia SAK%sT 1991 Mar 31 2:00s # Sakhalin T
- 10:00 Russia SAK%sT 1992 Jan 19 2:00s
- 11:00 Russia SAK%sT 1997 Mar lastSun 2:00s
- 10:00 Russia SAK%sT 2011 Mar 27 2:00s
- 11:00 - SAKT 2014 Oct 26 2:00s
- 10:00 - SAKT 2016 Mar 27 2:00s
- 11:00 - SAKT
+ 9:00 - +09 1945 Aug 25
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s # Sakhalin T
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 1997 Mar lastSun 2:00s
+ 10:00 Russia +10/+11 2011 Mar 27 2:00s
+ 11:00 - +11 2014 Oct 26 2:00s
+ 10:00 - +10 2016 Mar 27 2:00s
+ 11:00 - +11
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -3058,13 +3091,13 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23
# http://publication.pravo.gov.ru/Document/View/0001201604050038
Zone Asia/Magadan 10:03:12 - LMT 1924 May 2
- 10:00 - MAGT 1930 Jun 21 # Magadan Time
- 11:00 Russia MAG%sT 1991 Mar 31 2:00s
- 10:00 Russia MAG%sT 1992 Jan 19 2:00s
- 11:00 Russia MAG%sT 2011 Mar 27 2:00s
- 12:00 - MAGT 2014 Oct 26 2:00s
- 10:00 - MAGT 2016 Apr 24 2:00s
- 11:00 - MAGT
+ 10:00 - +10 1930 Jun 21 # Magadan Time
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12 2014 Oct 26 2:00s
+ 10:00 - +10 2016 Apr 24 2:00s
+ 11:00 - +11
# From Tim Parenti (2014-07-06):
@@ -3107,17 +3140,14 @@ Zone Asia/Magadan 10:03:12 - LMT 1924 May 2
# in Russian.) In addition, Srednekolymsk appears to be a much older
# settlement and the population of Zyryanka seems to be declining.
# Go with Srednekolymsk.
-#
-# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
-# as the abbreviation. Use SRET instead.
Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
- 10:00 - MAGT 1930 Jun 21 # Magadan Time
- 11:00 Russia MAG%sT 1991 Mar 31 2:00s
- 10:00 Russia MAG%sT 1992 Jan 19 2:00s
- 11:00 Russia MAG%sT 2011 Mar 27 2:00s
- 12:00 - MAGT 2014 Oct 26 2:00s
- 11:00 - SRET # Srednekolymsk Time
+ 10:00 - +10 1930 Jun 21
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12 2014 Oct 26 2:00s
+ 11:00 - +11
# From Tim Parenti (2014-07-03):
@@ -3135,14 +3165,14 @@ Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2
# UTC+12 since at least then, too.
Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15
- 8:00 - YAKT 1930 Jun 21 # Yakutsk Time
- 9:00 Russia YAKT 1981 Apr 1
- 11:00 Russia MAG%sT 1991 Mar 31 2:00s
- 10:00 Russia MAG%sT 1992 Jan 19 2:00s
- 11:00 Russia MAG%sT 2011 Mar 27 2:00s
- 12:00 - MAGT 2011 Sep 13 0:00s # Decree 725?
- 11:00 - VLAT 2014 Oct 26 2:00s
- 10:00 - VLAT
+ 8:00 - +08 1930 Jun 21
+ 9:00 Russia +09/+10 1981 Apr 1
+ 11:00 Russia +11/+12 1991 Mar 31 2:00s
+ 10:00 Russia +10/+11 1992 Jan 19 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12 2011 Sep 13 0:00s # Decree 725?
+ 11:00 - +11 2014 Oct 26 2:00s
+ 10:00 - +10
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -3155,12 +3185,12 @@ Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15
# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
# Asia/Petropavlovsk-Kamchatsky, but these are too long.
Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10
- 11:00 - PETT 1930 Jun 21 # P-K Time
- 12:00 Russia PET%sT 1991 Mar 31 2:00s
- 11:00 Russia PET%sT 1992 Jan 19 2:00s
- 12:00 Russia PET%sT 2010 Mar 28 2:00s
- 11:00 Russia PET%sT 2011 Mar 27 2:00s
- 12:00 - PETT
+ 11:00 - +11 1930 Jun 21
+ 12:00 Russia +12/+13 1991 Mar 31 2:00s
+ 11:00 Russia +11/+12 1992 Jan 19 2:00s
+ 12:00 Russia +12/+13 2010 Mar 28 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12
# From Tim Parenti (2014-07-03):
@@ -3168,13 +3198,13 @@ Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10
# 87 RU-CHU Chukotka Autonomous Okrug
Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2
- 12:00 - ANAT 1930 Jun 21 # Anadyr Time
- 13:00 Russia ANA%sT 1982 Apr 1 0:00s
- 12:00 Russia ANA%sT 1991 Mar 31 2:00s
- 11:00 Russia ANA%sT 1992 Jan 19 2:00s
- 12:00 Russia ANA%sT 2010 Mar 28 2:00s
- 11:00 Russia ANA%sT 2011 Mar 27 2:00s
- 12:00 - ANAT
+ 12:00 - +12 1930 Jun 21
+ 13:00 Russia +13/+14 1982 Apr 1 0:00s
+ 12:00 Russia +12/+13 1991 Mar 31 2:00s
+ 11:00 Russia +11/+12 1992 Jan 19 2:00s
+ 12:00 Russia +12/+13 2010 Mar 28 2:00s
+ 11:00 Russia +11/+12 2011 Mar 27 2:00s
+ 12:00 - +12
# San Marino
@@ -3433,22 +3463,24 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Turkey
-# From Amar Devegowda (2007-01-03):
-# The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at:
-# http://www.timeanddate.com/worldclock/timezone.html?n=107
-# From Steffen Thorsen (2007-01-03):
-# I have been able to find press records back to 1996 which all say that
-# DST started 01:00 local time and end at 02:00 local time. I am not sure
-# what happened before that. One example for each year from 1996 to 2001:
-# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
-# From Paul Eggert (2007-01-03):
-# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+# From Kıvanç Yazan (2016-09-25):
+# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
+# no exceptions.
+# 2) 1994's lastSun was overridden with Mar 20 ...
+# Here are official papers:
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf - page 2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf - page 4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf - page 15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf - page 6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf - page 1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf - page 15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf - page 1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf - page 1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2 - for 2001
+# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2 - for 2002-2006
+# From Paul Eggert (2016-09-25):
+# Prefer the above sources to Shanks & Pottenger for time stamps after 1985.
# From Steffen Thorsen (2007-03-09):
# Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
@@ -3495,6 +3527,14 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Engineered Standard Time," said Twitter user @aysekarahasan.
# http://www.bbc.com/news/world-europe-34631326
+# From Burak AYDIN (2016-09-08):
+# Turkey will stay in Daylight Saving Time even in winter....
+# http://www.resmigazete.gov.tr/eskiler/2016/09/20160908-2.pdf
+#
+# From Paul Eggert (2016-09-07):
+# The change is permanent, so this is the new standard time in Turkey.
+# It takes effect today, which is not much notice.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Turkey 1916 only - May 1 0:00 1:00 S
Rule Turkey 1916 only - Oct 1 0:00 0 -
@@ -3549,16 +3589,16 @@ Rule Turkey 1983 only - Jul 31 0:00 1:00 S
Rule Turkey 1983 only - Oct 2 0:00 0 -
Rule Turkey 1985 only - Apr 20 0:00 1:00 S
Rule Turkey 1985 only - Sep 28 0:00 0 -
-Rule Turkey 1986 1990 - Mar lastSun 2:00s 1:00 S
-Rule Turkey 1986 1990 - Sep lastSun 2:00s 0 -
-Rule Turkey 1991 2006 - Mar lastSun 1:00s 1:00 S
-Rule Turkey 1991 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1986 1993 - Mar lastSun 1:00s 1:00 S
+Rule Turkey 1986 1995 - Sep lastSun 1:00s 0 -
+Rule Turkey 1994 only - Mar 20 1:00s 1:00 S
+Rule Turkey 1995 2006 - Mar lastSun 1:00s 1:00 S
Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Istanbul 1:55:52 - LMT 1880
1:56:56 - IMT 1910 Oct # Istanbul Mean Time?
2:00 Turkey EE%sT 1978 Oct 15
- 3:00 Turkey TR%sT 1985 Apr 20 # Turkey Time
+ 3:00 Turkey +03/+04 1985 Apr 20
2:00 Turkey EE%sT 2007
2:00 EU EE%sT 2011 Mar 27 1:00u
2:00 - EET 2011 Mar 28 1:00u
@@ -3566,7 +3606,8 @@ Zone Europe/Istanbul 1:55:52 - LMT 1880
2:00 - EET 2014 Mar 31 1:00u
2:00 EU EE%sT 2015 Oct 25 1:00u
2:00 1:00 EEST 2015 Nov 8 1:00u
- 2:00 EU EE%sT
+ 2:00 EU EE%sT 2016 Sep 7
+ 3:00 - +03
Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
# Ukraine
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/factory b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/factory
index 0a6041d..7d79693 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/factory
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/factory
@@ -24,9 +24,10 @@
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
-# For companies who don't want to put time zone specification in
-# their installation procedures. When users run date, they'll get the message.
-# Also useful for the "comp.sources" version.
+# For distributors who don't want to put time zone specification in
+# their installation procedures. Users that run 'date' will get the
+# time zone abbreviation "-00", indicating that the actual time zone
+# is unknown.
# Zone NAME GMTOFF RULES FORMAT
-Zone Factory 0 - "Local time zone must be set--see zic manual page"
+Zone Factory 0 - -00
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/leapseconds b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/leapseconds
index a08fbc7..71d774d 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/leapseconds
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/leapseconds
@@ -79,6 +79,7 @@ Leap 2005 Dec 31 23:59:60 + S
Leap 2008 Dec 31 23:59:60 + S
Leap 2012 Jun 30 23:59:60 + S
Leap 2015 Jun 30 23:59:60 + S
+Leap 2016 Dec 31 23:59:60 + S
-# Updated through IERS Bulletin C51
-# File expires on: 28 December 2016
+# Updated through IERS Bulletin C52
+# File expires on: 28 June 2017
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/northamerica b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/northamerica
index ec59510..56b089c 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/northamerica
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/northamerica
@@ -47,8 +47,32 @@
# was the result of his proposals at the Convention of Railroad Trunk Lines
# in New York City (1869-10). His 1870 proposal was based on Washington, DC,
# but in 1872-05 he moved the proposed origin to Greenwich.
-# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
-# and the most of the country soon followed suit.
+
+# From Paul Eggert (2016-09-21):
+# Dowd's proposal left many details unresolved, such as where to draw
+# lines between time zones. The key individual who made time zones
+# work in the US was William Frederick Allen - railway engineer,
+# managing editor of the Travelers' Guide, and secretary of the
+# General Time Convention, a railway standardization group. Allen
+# spent months in dialogs with scientific and railway leaders,
+# developed a workable plan to institute time zones, and presented it
+# to the General Time Convention on 1883-04-11, saying that his plan
+# meant "local time would be practically abolished" - a plus for
+# railway scheduling. By the next convention on 1883-10-11 nearly all
+# railroads had agreed and it took effect on 1883-11-18 at 12:00.
+# That Sunday was called the "day of two noons", as the eastern parts
+# of the new zones observed noon twice. Allen witnessed the
+# transition in New York City, writing:
+#
+# I heard the bells of St. Paul's strike on the old time. Four
+# minutes later, obedient to the electrical signal from the Naval
+# Observatory ... the time-ball made its rapid descent, the chimes
+# of old Trinity rang twelve measured strokes, and local time was
+# abandoned, probably forever.
+#
+# Most of the US soon followed suit. See:
+# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56.
+# http://dx.doi.org/10.2307/3105430
# From Paul Eggert (2005-04-16):
# That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
@@ -436,11 +460,42 @@ Zone America/Denver -6:59:56 - LMT 1883 Nov 18 12:00:04
# north of the Salmon River, and the towns of Burgdorf and Warren),
# Nevada (except West Wendover), Oregon (except the northern 3/4 of
# Malheur county), and Washington
+
+# From Paul Eggert (2016-08-20):
+# In early February 1948, in response to California's electricity shortage,
+# PG&E changed power frequency from 60 to 59.5 Hz during daylight hours,
+# causing electric clocks to lose six minutes per day. (This did not change
+# legal time, and is not part of the data here.) See:
+# Ross SA. An energy crisis from the past: Northern California in 1948.
+# Working Paper No. 8, Institute of Governmental Studies, UC Berkeley,
+# 1973-11. http://escholarship.org/uc/item/8x22k30c
+#
+# In another measure to save electricity, DST was instituted from 1948-03-14
+# at 02:01 to 1949-01-16 at 02:00, with the governor having the option to move
+# the fallback transition earlier. See pages 3-4 of:
+# http://clerk.assembly.ca.gov/sites/clerk.assembly.ca.gov/files/archive/Statutes/1948/48Vol1_Chapters.pdf
+#
+# In response:
+#
+# Governor Warren received a torrent of objecting mail, and it is not too much
+# to speculate that the objections to Daylight Saving Time were one important
+# factor in the defeat of the Dewey-Warren Presidential ticket in California.
+# -- Ross, p 25
+#
+# On December 8 the governor exercised the option, setting the date to January 1
+# (LA Times 1948-12-09). The transition time was 02:00 (LA Times 1949-01-01).
+#
+# Despite the controversy, in 1949 California voters approved Proposition 12,
+# which established DST from April's last Sunday at 01:00 until September's
+# last Sunday at 02:00. This was amended by 1962's Proposition 6, which changed
+# the fall-back date to October's last Sunday. See:
+# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1501&context=ca_ballot_props
+# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1636&context=ca_ballot_props
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
-Rule CA 1948 only - Mar 14 2:00 1:00 D
+Rule CA 1948 only - Mar 14 2:01 1:00 D
Rule CA 1949 only - Jan 1 2:00 0 S
-Rule CA 1950 1966 - Apr lastSun 2:00 1:00 D
+Rule CA 1950 1966 - Apr lastSun 1:00 1:00 D
Rule CA 1950 1961 - Sep lastSun 2:00 0 S
Rule CA 1962 1966 - Oct lastSun 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -3304,7 +3359,7 @@ Zone America/Miquelon -3:44:40 - LMT 1911 May 15 # St Pierre
# indicating that the normal ET rules are followed.
#
# From Paul Eggert (2014-08-19):
-# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round. See:
+# The 2014-08-13 Cabinet meeting decided to stay on UT -04 year-round. See:
# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
# Model this as a switch from EST/EDT to AST ...
# From Chris Walton (2014-11-04):
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/southamerica b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/southamerica
index 08c89ca..bbc0a95 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/southamerica
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/southamerica
@@ -433,9 +433,9 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
# stuck on Summer daylight savings time even though the summer is over.
# From Paul Eggert (2013-09-05):
-# Perhaps San Luis operates on the legal fiction that it is at UTC-4
+# Perhaps San Luis operates on the legal fiction that it is at -04
# with perpetual summer time, but ordinary usage typically seems to
-# just say it's at UTC-3; see, for example,
+# just say it's at -03; see, for example,
# http://es.wikipedia.org/wiki/Hora_oficial_argentina
# We've documented similar situations as being plain changes to
# standard time, so let's do that here too. This does not change UTC
diff --git a/openjdk/jdk/test/sun/util/calendar/zi/tzdata/zone.tab b/openjdk/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
index 5649691..2de07ef 100644
--- openjdk/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
+++ openjdk/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
@@ -175,7 +175,8 @@ CU +2308-08222 America/Havana
CV +1455-02331 Atlantic/Cape_Verde
CW +1211-06900 America/Curacao
CX -1025+10543 Indian/Christmas
-CY +3510+03322 Asia/Nicosia
+CY +3510+03322 Asia/Nicosia Cyprus (most areas)
+CY +3507+03357 Asia/Famagusta Northern Cyprus
CZ +5005+01426 Europe/Prague
DE +5230+01322 Europe/Berlin Germany (most areas)
DE +4742+00841 Europe/Busingen Busingen
@@ -284,7 +285,7 @@ MH +0709+17112 Pacific/Majuro Marshall Islands (most areas)
MH +0905+16720 Pacific/Kwajalein Kwajalein
MK +4159+02126 Europe/Skopje
ML +1239-00800 Africa/Bamako
-MM +1647+09610 Asia/Rangoon
+MM +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas)
MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
index 10caa40..697ab82 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@ import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.StringUtils;
+import com.sun.tools.javadoc.JavaScriptScanner;
import com.sun.tools.javadoc.RootDocImpl;
/**
@@ -181,6 +182,11 @@ public class ConfigurationImpl extends Configuration {
public Set<String> doclintOpts = new LinkedHashSet<String>();
/**
+ * Whether or not to check for JavaScript in doc comments.
+ */
+ private boolean allowScriptInComments;
+
+ /**
* Unique Resource Handler for this package.
*/
public final MessageRetriever standardmessage;
@@ -283,8 +289,11 @@ public class ConfigurationImpl extends Configuration {
doclintOpts.add(null);
} else if (opt.startsWith("-xdoclint:")) {
doclintOpts.add(opt.substring(opt.indexOf(":") + 1));
+ } else if (opt.equals("--allow-script-in-comments")) {
+ allowScriptInComments = true;
}
}
+
if (root.specifiedClasses().length > 0) {
Map<String,PackageDoc> map = new HashMap<String,PackageDoc>();
PackageDoc pd;
@@ -301,9 +310,30 @@ public class ConfigurationImpl extends Configuration {
if (root instanceof RootDocImpl) {
((RootDocImpl) root).initDocLint(doclintOpts, tagletManager.getCustomTagNames());
+ JavaScriptScanner jss = ((RootDocImpl) root).initJavaScriptScanner(isAllowScriptInComments());
+ if (jss != null) {
+ // In a more object-oriented world, this would be done by methods on the Option objects.
+ // Note that -windowtitle silently removes any and all HTML elements, and so does not need
+ // to be handled here.
+ checkJavaScript(jss, "-header", header);
+ checkJavaScript(jss, "-footer", footer);
+ checkJavaScript(jss, "-top", top);
+ checkJavaScript(jss, "-bottom", bottom);
+ checkJavaScript(jss, "-doctitle", doctitle);
+ checkJavaScript(jss, "-packagesheader", packagesheader);
+ }
}
}
+ private void checkJavaScript(JavaScriptScanner jss, final String opt, String value) {
+ jss.parse(value, new JavaScriptScanner.Reporter() {
+ public void report() {
+ root.printError(getText("doclet.JavaScript_in_option", opt));
+ throw new FatalError();
+ }
+ });
+ }
+
/**
* Returns the "length" of a given option. If an option takes no
* arguments, its length is one. If it takes one argument, it's
@@ -337,7 +367,8 @@ public class ConfigurationImpl extends Configuration {
option.equals("-nonavbar") ||
option.equals("-nooverview") ||
option.equals("-xdoclint") ||
- option.startsWith("-xdoclint:")) {
+ option.startsWith("-xdoclint:") ||
+ option.equals("--allow-script-in-comments")) {
return 1;
} else if (option.equals("-help")) {
// Uugh: first, this should not be hidden inside optionLength,
@@ -595,4 +626,13 @@ public class ConfigurationImpl extends Configuration {
public Content newContent() {
return new ContentBuilder();
}
+
+ /**
+ * Returns whether or not to allow JavaScript in comments.
+ * Default is off; can be set true from a command line option.
+ * @return the allowScriptInComments
+ */
+ public boolean isAllowScriptInComments() {
+ return allowScriptInComments;
+ }
}
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
index 5cf8337..8377a14 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -190,6 +190,8 @@ public class HtmlDoclet extends AbstractDoclet {
}
} catch (IOException e) {
throw new DocletAbortException(e);
+ } catch (FatalError fe) {
+ throw fe;
} catch (DocletAbortException de) {
throw de;
} catch (Exception e) {
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
index d15459e..84fec05 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -164,7 +164,9 @@ public class HtmlWriter {
public final Content descfrmInterfaceLabel;
- private final Writer writer;
+ private final DocFile file;
+
+ private Writer writer;
private Content script;
@@ -180,7 +182,7 @@ public class HtmlWriter {
*/
public HtmlWriter(Configuration configuration, DocPath path)
throws IOException, UnsupportedEncodingException {
- writer = DocFile.createFileForOutput(configuration, path).openWriter();
+ file = DocFile.createFileForOutput(configuration, path);
this.configuration = configuration;
this.memberDetailsListPrinted = false;
profileTableHeader = new String[] {
@@ -239,6 +241,7 @@ public class HtmlWriter {
}
public void write(Content c) throws IOException {
+ writer = file.openWriter();
c.write(writer, true);
}
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
index 39fde45..35f979d 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,8 @@ public abstract class AbstractDoclet {
} catch (Configuration.Fault f) {
root.printError(f.getMessage());
return false;
+ } catch (FatalError fe) {
+ return false;
} catch (DocletAbortException e) {
Throwable cause = e.getCause();
if (cause != null) {
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
index 00f0b2b..b30e156 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,14 @@ public abstract class AbstractBuilder {
configuration.root.printError("Unknown element: " + component);
throw new DocletAbortException(e);
} catch (InvocationTargetException e) {
- throw new DocletAbortException(e.getCause());
+ Throwable cause = e.getCause();
+ if (cause instanceof FatalError) {
+ throw (FatalError) cause;
+ } else if (cause instanceof DocletAbortException) {
+ throw (DocletAbortException) cause;
+ } else {
+ throw new DocletAbortException(cause);
+ }
} catch (Exception e) {
e.printStackTrace();
configuration.root.printError("Exception " +
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
index 597dd35..dad5ab8 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
@@ -29,6 +29,8 @@ doclet.Encoding_not_supported=Encoding not supported: {0}
doclet.Building_Tree=Building tree for all the packages and classes...
doclet.Building_Index=Building index for all the packages and classes...
doclet.Building_Index_For_All_Classes=Building index for all classes...
+doclet.JavaScript_in_option=Argument for {0} contains JavaScript.\n\
+Use --allow-script-in-comments to allow use of JavaScript.
doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
doclet.Packages=Packages
doclet.Profiles=Profiles
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties
index 8051a49..3b6f660 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties
@@ -27,6 +27,7 @@ doclet.Encoding_not_supported=\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0{0
doclet.Building_Tree=\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u3068\u30AF\u30E9\u30B9\u306E\u968E\u5C64\u30C4\u30EA\u30FC\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059...
doclet.Building_Index=\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u3068\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059...
doclet.Building_Index_For_All_Classes=\u5168\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059...
+doclet.JavaScript_in_option={0}\u306E\u5F15\u6570\u306BJavaScript\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\n--allow-script-in-comments\u3092\u4F7F\u7528\u3057\u3066\u3001JavaScript\u306E\u4F7F\u7528\u3092\u8A31\u53EF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
doclet.sourcetab_warning=-sourcetab\u306E\u5F15\u6570\u306F0\u3088\u308A\u5927\u304D\u3044\u6574\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
doclet.Packages=\u30D1\u30C3\u30B1\u30FC\u30B8
doclet.Profiles=\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties
index d67b248..3fff28a 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties
@@ -27,6 +27,7 @@ doclet.Encoding_not_supported=\u4E0D\u652F\u6301\u7F16\u7801: {0}
doclet.Building_Tree=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u6811...
doclet.Building_Index=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u7D22\u5F15...
doclet.Building_Index_For_All_Classes=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7C7B\u7684\u7D22\u5F15...
+doclet.JavaScript_in_option={0} \u7684\u53C2\u6570\u5305\u542B JavaScript\u3002\n\u4F7F\u7528 --allow-script-in-comments \u53EF\u5141\u8BB8\u4F7F\u7528 JavaScript\u3002
doclet.sourcetab_warning=-sourcetab \u7684\u53C2\u6570\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570\u3002
doclet.Packages=\u7A0B\u5E8F\u5305
doclet.Profiles=\u914D\u7F6E\u6587\u4EF6
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java
new file mode 100644
index 0000000..71248cb
--- /dev/null
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.doclets.internal.toolkit.util;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+@Deprecated
+public class FatalError extends Error {
+ private static final long serialVersionUID = -9131058909576418984L;
+
+ public FatalError() { }
+}
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclint/Checker.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclint/Checker.java
index e89a460..dd9f7f4 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclint/Checker.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclint/Checker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,7 +126,7 @@ public class Checker extends DocTreePathScanner<Void, Void> {
}
}
- private Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
+ private final Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
private HtmlTag currHeaderTag;
private final int implicitHeaderLevel;
@@ -401,7 +401,16 @@ public class Checker extends DocTreePathScanner<Void, Void> {
break;
case OTHER:
- env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
+ switch (t) {
+ case SCRIPT:
+ // <script> may or may not be allowed, depending on --allow-script-in-comments
+ // but we allow it here, and rely on a separate scanner to detect all uses
+ // of JavaScript, including <script> tags, and use in attributes, etc.
+ break;
+
+ default:
+ env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
+ }
return;
}
@@ -519,22 +528,27 @@ public class Checker extends DocTreePathScanner<Void, Void> {
if (!first)
env.messages.error(HTML, tree, "dc.attr.repeated", name);
}
- AttrKind k = currTag.getAttrKind(name);
- switch (k) {
- case OK:
- break;
- case INVALID:
- env.messages.error(HTML, tree, "dc.attr.unknown", name);
- break;
+ // for now, doclint allows all attribute names beginning with "on" as event handler names,
+ // without checking the validity or applicability of the name
+ if (!name.toString().startsWith("on")) {
+ AttrKind k = currTag.getAttrKind(name);
+ switch (k) {
+ case OK:
+ break;
- case OBSOLETE:
- env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
- break;
+ case INVALID:
+ env.messages.error(HTML, tree, "dc.attr.unknown", name);
+ break;
- case USE_CSS:
- env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
- break;
+ case OBSOLETE:
+ env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
+ break;
+
+ case USE_CSS:
+ env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
+ break;
+ }
}
if (attr != null) {
@@ -643,6 +657,9 @@ public class Checker extends DocTreePathScanner<Void, Void> {
}
private void checkURI(AttributeTree tree, String uri) {
+ // allow URIs beginning with javascript:, which would otherwise be rejected by the URI API.
+ if (uri.startsWith("javascript:"))
+ return;
try {
URI u = new URI(uri);
} catch (URISyntaxException e) {
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java b/openjdk/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
index 8de4327..99d384e 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -183,7 +183,8 @@ public enum HtmlTag {
}
},
- SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
+ SCRIPT(BlockType.OTHER, EndKind.REQUIRED,
+ attrs(AttrKind.OK, SRC)),
SMALL(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)),
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/openjdk/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 9cdb462..e61ea49 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -585,7 +585,7 @@ public class JavacParser implements Parser {
/**
* Ident = IDENTIFIER
*/
- Name ident() {
+ public Name ident() {
if (token.kind == IDENTIFIER) {
Name name = token.name();
nextToken();
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
index 49933a8..3db4597 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -86,7 +86,7 @@ public class DocEnv {
JavadocEnter enter;
/** The name table. */
- Names names;
+ private final Names names;
/** The encoding name. */
private String encoding;
@@ -109,6 +109,7 @@ public class DocEnv {
JavaFileManager fileManager;
Context context;
DocLint doclint;
+ JavaScriptScanner javaScriptScanner;
WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<JCTree, TreePath>();
@@ -834,6 +835,15 @@ public class DocEnv {
doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
}
+ JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
+ if (allowScriptInComments) {
+ javaScriptScanner = null;
+ } else {
+ javaScriptScanner = new JavaScriptScanner();
+ }
+ return javaScriptScanner;
+ }
+
boolean showTagMessages() {
return (doclint == null);
}
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java
index e5b3f6c..83f5581 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@ import javax.tools.FileObject;
import com.sun.javadoc.*;
import com.sun.source.util.TreePath;
+import com.sun.tools.doclets.internal.toolkit.util.FatalError;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Position;
@@ -127,6 +128,15 @@ public abstract class DocImpl implements Doc, Comparable<Object> {
Comment comment() {
if (comment == null) {
String d = documentation();
+ if (env.javaScriptScanner != null) {
+ env.javaScriptScanner.parse(d, new JavaScriptScanner.Reporter() {
+ @Override
+ public void report() {
+ env.error(DocImpl.this, "javadoc.JavaScript_in_comment");
+ throw new FatalError();
+ }
+ });
+ }
if (env.doclint != null
&& treePath != null
&& d.equals(getCommentText(treePath))) {
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java
new file mode 100644
index 0000000..2ef0d7a
--- /dev/null
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javadoc;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import com.sun.tools.javadoc.JavaScriptScanner.TagParser.Kind;
+
+import static com.sun.tools.javac.util.LayoutCharacters.EOI;
+
+/**
+ * Parser to detect use of JavaScript in documentation comments.
+ */
+@Deprecated
+public class JavaScriptScanner {
+ public static interface Reporter {
+ void report();
+ }
+
+ static class ParseException extends Exception {
+ private static final long serialVersionUID = 0;
+ ParseException(String key) {
+ super(key);
+ }
+ }
+
+ private Reporter reporter;
+
+ /** The input buffer, index of most recent character read,
+ * index of one past last character in buffer.
+ */
+ protected char[] buf;
+ protected int bp;
+ protected int buflen;
+
+ /** The current character.
+ */
+ protected char ch;
+
+ private boolean newline = true;
+
+ Map<String, TagParser> tagParsers;
+ Set<String> eventAttrs;
+ Set<String> uriAttrs;
+
+ public JavaScriptScanner() {
+ initTagParsers();
+ initEventAttrs();
+ initURIAttrs();
+ }
+
+ public void parse(String comment, Reporter r) {
+ reporter = r;
+ String c = comment;
+ buf = new char[c.length() + 1];
+ c.getChars(0, c.length(), buf, 0);
+ buf[buf.length - 1] = EOI;
+ buflen = buf.length - 1;
+ bp = -1;
+ newline = true;
+ nextChar();
+
+ blockContent();
+ blockTags();
+ }
+
+ private void checkHtmlTag(String tag) {
+ if (tag.equalsIgnoreCase("script")) {
+ reporter.report();
+ }
+ }
+
+ private void checkHtmlAttr(String name, String value) {
+ String n = name.toLowerCase(Locale.ENGLISH);
+ if (eventAttrs.contains(n)
+ || uriAttrs.contains(n)
+ && value != null && value.toLowerCase(Locale.ENGLISH).trim().startsWith("javascript:")) {
+ reporter.report();
+ }
+ }
+
+ void nextChar() {
+ ch = buf[bp < buflen ? ++bp : buflen];
+ switch (ch) {
+ case '\f': case '\n': case '\r':
+ newline = true;
+ }
+ }
+
+ /**
+ * Read block content, consisting of text, html and inline tags.
+ * Terminated by the end of input, or the beginning of the next block tag:
+ * i.e. @ as the first non-whitespace character on a line.
+ */
+ @SuppressWarnings("fallthrough")
+ protected void blockContent() {
+
+ loop:
+ while (bp < buflen) {
+ switch (ch) {
+ case '\n': case '\r': case '\f':
+ newline = true;
+ // fallthrough
+
+ case ' ': case '\t':
+ nextChar();
+ break;
+
+ case '&':
+ entity(null);
+ break;
+
+ case '<':
+ html();
+ break;
+
+ case '>':
+ newline = false;
+ nextChar();
+ break;
+
+ case '{':
+ inlineTag(null);
+ break;
+
+ case '@':
+ if (newline) {
+ break loop;
+ }
+ // fallthrough
+
+ default:
+ newline = false;
+ nextChar();
+ }
+ }
+ }
+
+ /**
+ * Read a series of block tags, including their content.
+ * Standard tags parse their content appropriately.
+ * Non-standard tags are represented by {@link UnknownBlockTag}.
+ */
+ protected void blockTags() {
+ while (ch == '@')
+ blockTag();
+ }
+
+ /**
+ * Read a single block tag, including its content.
+ * Standard tags parse their content appropriately.
+ * Non-standard tags are represented by {@link UnknownBlockTag}.
+ */
+ protected void blockTag() {
+ int p = bp;
+ try {
+ nextChar();
+ if (isIdentifierStart(ch)) {
+ String name = readTagName();
+ TagParser tp = tagParsers.get(name);
+ if (tp == null) {
+ blockContent();
+ } else {
+ switch (tp.getKind()) {
+ case BLOCK:
+ tp.parse(p);
+ return;
+ case INLINE:
+ return;
+ }
+ }
+ }
+ blockContent();
+ } catch (ParseException e) {
+ blockContent();
+ }
+ }
+
+ protected void inlineTag(Void list) {
+ newline = false;
+ nextChar();
+ if (ch == '@') {
+ inlineTag();
+ }
+ }
+
+ /**
+ * Read a single inline tag, including its content.
+ * Standard tags parse their content appropriately.
+ * Non-standard tags are represented by {@link UnknownBlockTag}.
+ * Malformed tags may be returned as {@link Erroneous}.
+ */
+ protected void inlineTag() {
+ int p = bp - 1;
+ try {
+ nextChar();
+ if (isIdentifierStart(ch)) {
+ String name = readTagName();
+ TagParser tp = tagParsers.get(name);
+
+ if (tp == null) {
+ skipWhitespace();
+ inlineText(WhitespaceRetentionPolicy.REMOVE_ALL);
+ nextChar();
+ } else {
+ skipWhitespace();
+ if (tp.getKind() == TagParser.Kind.INLINE) {
+ tp.parse(p);
+ } else { // handle block tags (ex: @see) in inline content
+ inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip content
+ nextChar();
+ }
+ }
+ }
+ } catch (ParseException e) {
+ }
+ }
+
+ private static enum WhitespaceRetentionPolicy {
+ RETAIN_ALL,
+ REMOVE_FIRST_SPACE,
+ REMOVE_ALL
+ }
+
+ /**
+ * Read plain text content of an inline tag.
+ * Matching pairs of { } are skipped; the text is terminated by the first
+ * unmatched }. It is an error if the beginning of the next tag is detected.
+ */
+ private void inlineText(WhitespaceRetentionPolicy whitespacePolicy) throws ParseException {
+ switch (whitespacePolicy) {
+ case REMOVE_ALL:
+ skipWhitespace();
+ break;
+ case REMOVE_FIRST_SPACE:
+ if (ch == ' ')
+ nextChar();
+ break;
+ case RETAIN_ALL:
+ default:
+ // do nothing
+ break;
+
+ }
+ int pos = bp;
+ int depth = 1;
+
+ loop:
+ while (bp < buflen) {
+ switch (ch) {
+ case '\n': case '\r': case '\f':
+ newline = true;
+ break;
+
+ case ' ': case '\t':
+ break;
+
+ case '{':
+ newline = false;
+ depth++;
+ break;
+
+ case '}':
+ if (--depth == 0) {
+ return;
+ }
+ newline = false;
+ break;
+
+ case '@':
+ if (newline)
+ break loop;
+ newline = false;
+ break;
+
+ default:
+ newline = false;
+ break;
+ }
+ nextChar();
+ }
+ throw new ParseException("dc.unterminated.inline.tag");
+ }
+
+ /**
+ * Read Java class name, possibly followed by member
+ * Matching pairs of {@literal < >} are skipped. The text is terminated by the first
+ * unmatched }. It is an error if the beginning of the next tag is detected.
+ */
+ // TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE
+ // TODO: improve quality of parse to forbid bad constructions.
+ // TODO: update to use ReferenceParser
+ @SuppressWarnings("fallthrough")
+ protected void reference(boolean allowMember) throws ParseException {
+ int pos = bp;
+ int depth = 0;
+
+ // scan to find the end of the signature, by looking for the first
+ // whitespace not enclosed in () or <>, or the end of the tag
+ loop:
+ while (bp < buflen) {
+ switch (ch) {
+ case '\n': case '\r': case '\f':
+ newline = true;
+ // fallthrough
+
+ case ' ': case '\t':
+ if (depth == 0)
+ break loop;
+ break;
+
+ case '(':
+ case '<':
+ newline = false;
+ depth++;
+ break;
+
+ case ')':
+ case '>':
+ newline = false;
+ --depth;
+ break;
+
+ case '}':
+ if (bp == pos)
+ return;
+ newline = false;
+ break loop;
+
+ case '@':
+ if (newline)
+ break loop;
+ // fallthrough
+
+ default:
+ newline = false;
+
+ }
+ nextChar();
+ }
+
+ if (depth != 0)
+ throw new ParseException("dc.unterminated.signature");
+ }
+
+ /**
+ * Read Java identifier
+ * Matching pairs of { } are skipped; the text is terminated by the first
+ * unmatched }. It is an error if the beginning of the next tag is detected.
+ */
+ @SuppressWarnings("fallthrough")
+ protected void identifier() throws ParseException {
+ skipWhitespace();
+ int pos = bp;
+
+ if (isJavaIdentifierStart(ch)) {
+ readJavaIdentifier();
+ return;
+ }
+
+ throw new ParseException("dc.identifier.expected");
+ }
+
+ /**
+ * Read a quoted string.
+ * It is an error if the beginning of the next tag is detected.
+ */
+ @SuppressWarnings("fallthrough")
+ protected void quotedString() {
+ int pos = bp;
+ nextChar();
+
+ loop:
+ while (bp < buflen) {
+ switch (ch) {
+ case '\n': case '\r': case '\f':
+ newline = true;
+ break;
+
+ case ' ': case '\t':
+ break;
+
+ case '"':
+ nextChar();
+ // trim trailing white-space?
+ return;
+
+ case '@':
+ if (newline)
+ break loop;
+
+ }
+ nextChar();
+ }
+ }
+
+ /**
+ * Read a term ie. one word.
+ * It is an error if the beginning of the next tag is detected.
+ */
+ @SuppressWarnings("fallthrough")
+ protected void inlineWord() {
+ int pos = bp;
+ int depth = 0;
+ loop:
+ while (bp < buflen) {
+ switch (ch) {
+ case '\n':
+ newline = true;
+ // fallthrough
+
+ case '\r': case '\f': case ' ': case '\t':
+ return;
+
+ case '@':
+ if (newline)
+ break loop;
+
+ case '{':
+ depth++;
+ break;
+
+ case '}':
+ if (depth == 0 || --depth == 0)
+ return;
+ break;
+ }
+ newline = false;
+ nextChar();
+ }
+ }
+
+ /**
+ * Read general text content of an inline tag, including HTML entities and elements.
+ * Matching pairs of { } are skipped; the text is terminated by the first
+ * unmatched }. It is an error if the beginning of the next tag is detected.
+ */
+ @SuppressWarnings("fallthrough")
+ private void inlineContent() {
+
+ skipWhitespace();
+ int pos = bp;
+ int depth = 1;
+
+ loop:
+ while (bp < buflen) {
+
+ switch (ch) {
+ case '\n': case '\r': case '\f':
+ newline = true;
+ // fall through
+
+ case ' ': case '\t':
+ nextChar();
+ break;
+
+ case '&':
+ entity(null);
+ break;
+
+ case '<':
+ newline = false;
+ html();
+ break;
+
+ case '{':
+ newline = false;
+ depth++;
+ nextChar();
+ break;
+
+ case '}':
+ newline = false;
+ if (--depth == 0) {
+ nextChar();
+ return;
+ }
+ nextChar();
+ break;
+
+ case '@':
+ if (newline)
+ break loop;
+ // fallthrough
+
+ default:
+ nextChar();
+ break;
+ }
+ }
+
+ }
+
+ protected void entity(Void list) {
+ newline = false;
+ entity();
+ }
+
+ /**
+ * Read an HTML entity.
+ * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; }
+ */
+ protected void entity() {
+ nextChar();
+ String name = null;
+ if (ch == '#') {
+ int namep = bp;
+ nextChar();
+ if (isDecimalDigit(ch)) {
+ nextChar();
+ while (isDecimalDigit(ch))
+ nextChar();
+ name = new String(buf, namep, bp - namep);
+ } else if (ch == 'x' || ch == 'X') {
+ nextChar();
+ if (isHexDigit(ch)) {
+ nextChar();
+ while (isHexDigit(ch))
+ nextChar();
+ name = new String(buf, namep, bp - namep);
+ }
+ }
+ } else if (isIdentifierStart(ch)) {
+ name = readIdentifier();
+ }
+
+ if (name != null) {
+ if (ch != ';')
+ return;
+ nextChar();
+ }
+ }
+
+ /**
+ * Read the start or end of an HTML tag, or an HTML comment
+ * {@literal <identifier attrs> } or {@literal </identifier> }
+ */
+ protected void html() {
+ int p = bp;
+ nextChar();
+ if (isIdentifierStart(ch)) {
+ String name = readIdentifier();
+ checkHtmlTag(name);
+ htmlAttrs();
+ if (ch == '/') {
+ nextChar();
+ }
+ if (ch == '>') {
+ nextChar();
+ return;
+ }
+ } else if (ch == '/') {
+ nextChar();
+ if (isIdentifierStart(ch)) {
+ readIdentifier();
+ skipWhitespace();
+ if (ch == '>') {
+ nextChar();
+ return;
+ }
+ }
+ } else if (ch == '!') {
+ nextChar();
+ if (ch == '-') {
+ nextChar();
+ if (ch == '-') {
+ nextChar();
+ while (bp < buflen) {
+ int dash = 0;
+ while (ch == '-') {
+ dash++;
+ nextChar();
+ }
+ // Strictly speaking, a comment should not contain "--"
+ // so dash > 2 is an error, dash == 2 implies ch == '>'
+ // See http://www.w3.org/TR/html-markup/syntax.html#syntax-comments
+ // for more details.
+ if (dash >= 2 && ch == '>') {
+ nextChar();
+ return;
+ }
+
+ nextChar();
+ }
+ }
+ }
+ }
+
+ bp = p + 1;
+ ch = buf[bp];
+ }
+
+ /**
+ * Read a series of HTML attributes, terminated by {@literal > }.
+ * Each attribute is of the form {@literal identifier[=value] }.
+ * "value" may be unquoted, single-quoted, or double-quoted.
+ */
+ protected void htmlAttrs() {
+ skipWhitespace();
+
+ loop:
+ while (isIdentifierStart(ch)) {
+ int namePos = bp;
+ String name = readAttributeName();
+ skipWhitespace();
+ StringBuilder value = new StringBuilder();
+ if (ch == '=') {
+ nextChar();
+ skipWhitespace();
+ if (ch == '\'' || ch == '"') {
+ char quote = ch;
+ nextChar();
+ while (bp < buflen && ch != quote) {
+ if (newline && ch == '@') {
+ // No point trying to read more.
+ // In fact, all attrs get discarded by the caller
+ // and superseded by a malformed.html node because
+ // the html tag itself is not terminated correctly.
+ break loop;
+ }
+ value.append(ch);
+ nextChar();
+ }
+ nextChar();
+ } else {
+ while (bp < buflen && !isUnquotedAttrValueTerminator(ch)) {
+ value.append(ch);
+ nextChar();
+ }
+ }
+ skipWhitespace();
+ }
+ checkHtmlAttr(name, value.toString());
+ }
+ }
+
+ protected void attrValueChar(Void list) {
+ switch (ch) {
+ case '&':
+ entity(list);
+ break;
+
+ case '{':
+ inlineTag(list);
+ break;
+
+ default:
+ nextChar();
+ }
+ }
+
+ protected boolean isIdentifierStart(char ch) {
+ return Character.isUnicodeIdentifierStart(ch);
+ }
+
+ protected String readIdentifier() {
+ int start = bp;
+ nextChar();
+ while (bp < buflen && Character.isUnicodeIdentifierPart(ch))
+ nextChar();
+ return new String(buf, start, bp - start);
+ }
+
+ protected String readAttributeName() {
+ int start = bp;
+ nextChar();
+ while (bp < buflen && (Character.isUnicodeIdentifierPart(ch) || ch == '-'))
+ nextChar();
+ return new String(buf, start, bp - start);
+ }
+
+ protected String readTagName() {
+ int start = bp;
+ nextChar();
+ while (bp < buflen
+ && (Character.isUnicodeIdentifierPart(ch) || ch == '.'
+ || ch == '-' || ch == ':')) {
+ nextChar();
+ }
+ return new String(buf, start, bp - start);
+ }
+
+ protected boolean isJavaIdentifierStart(char ch) {
+ return Character.isJavaIdentifierStart(ch);
+ }
+
+ protected String readJavaIdentifier() {
+ int start = bp;
+ nextChar();
+ while (bp < buflen && Character.isJavaIdentifierPart(ch))
+ nextChar();
+ return new String(buf, start, bp - start);
+ }
+
+ protected boolean isDecimalDigit(char ch) {
+ return ('0' <= ch && ch <= '9');
+ }
+
+ protected boolean isHexDigit(char ch) {
+ return ('0' <= ch && ch <= '9')
+ || ('a' <= ch && ch <= 'f')
+ || ('A' <= ch && ch <= 'F');
+ }
+
+ protected boolean isUnquotedAttrValueTerminator(char ch) {
+ switch (ch) {
+ case '\f': case '\n': case '\r': case '\t':
+ case ' ':
+ case '"': case '\'': case '`':
+ case '=': case '<': case '>':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ protected boolean isWhitespace(char ch) {
+ return Character.isWhitespace(ch);
+ }
+
+ protected void skipWhitespace() {
+ while (isWhitespace(ch)) {
+ nextChar();
+ }
+ }
+
+ /**
+ * @param start position of first character of string
+ * @param end position of character beyond last character to be included
+ */
+ String newString(int start, int end) {
+ return new String(buf, start, end - start);
+ }
+
+ static abstract class TagParser {
+ enum Kind { INLINE, BLOCK }
+
+ final Kind kind;
+ final String name;
+
+
+ TagParser(Kind k, String tk) {
+ kind = k;
+ name = tk;
+ }
+
+ TagParser(Kind k, String tk, boolean retainWhiteSpace) {
+ this(k, tk);
+ }
+
+ Kind getKind() {
+ return kind;
+ }
+
+ String getName() {
+ return name;
+ }
+
+ abstract void parse(int pos) throws ParseException;
+ }
+
+ /**
+ * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javadoc.html#javadoctags">Javadoc Tags</a>
+ */
+ @SuppressWarnings("deprecation")
+ private void initTagParsers() {
+ TagParser[] parsers = {
+ // @author name-text
+ new TagParser(Kind.BLOCK, "author") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // {@code text}
+ new TagParser(Kind.INLINE, "code", true) {
+ @Override
+ public void parse(int pos) throws ParseException {
+ inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE);
+ nextChar();
+ }
+ },
+
+ // @deprecated deprecated-text
+ new TagParser(Kind.BLOCK, "deprecated") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // {@docRoot}
+ new TagParser(Kind.INLINE, "docRoot") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ if (ch == '}') {
+ nextChar();
+ return;
+ }
+ inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content
+ nextChar();
+ throw new ParseException("dc.unexpected.content");
+ }
+ },
+
+ // @exception class-name description
+ new TagParser(Kind.BLOCK, "exception") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ skipWhitespace();
+ reference(false);
+ blockContent();
+ }
+ },
+
+ // @hidden hidden-text
+ new TagParser(Kind.BLOCK, "hidden") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // @index search-term options-description
+ new TagParser(Kind.INLINE, "index") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ skipWhitespace();
+ if (ch == '}') {
+ throw new ParseException("dc.no.content");
+ }
+ if (ch == '"') quotedString(); else inlineWord();
+ skipWhitespace();
+ if (ch != '}') {
+ inlineContent();
+ } else {
+ nextChar();
+ }
+ }
+ },
+
+ // {@inheritDoc}
+ new TagParser(Kind.INLINE, "inheritDoc") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ if (ch == '}') {
+ nextChar();
+ return;
+ }
+ inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content
+ nextChar();
+ throw new ParseException("dc.unexpected.content");
+ }
+ },
+
+ // {@link package.class#member label}
+ new TagParser(Kind.INLINE, "link") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ reference(true);
+ inlineContent();
+ }
+ },
+
+ // {@linkplain package.class#member label}
+ new TagParser(Kind.INLINE, "linkplain") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ reference(true);
+ inlineContent();
+ }
+ },
+
+ // {@literal text}
+ new TagParser(Kind.INLINE, "literal", true) {
+ @Override
+ public void parse(int pos) throws ParseException {
+ inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE);
+ nextChar();
+ }
+ },
+
+ // @param parameter-name description
+ new TagParser(Kind.BLOCK, "param") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ skipWhitespace();
+
+ boolean typaram = false;
+ if (ch == '<') {
+ typaram = true;
+ nextChar();
+ }
+
+ identifier();
+
+ if (typaram) {
+ if (ch != '>')
+ throw new ParseException("dc.gt.expected");
+ nextChar();
+ }
+
+ skipWhitespace();
+ blockContent();
+ }
+ },
+
+ // @return description
+ new TagParser(Kind.BLOCK, "return") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // @see reference | quoted-string | HTML
+ new TagParser(Kind.BLOCK, "see") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ skipWhitespace();
+ switch (ch) {
+ case '"':
+ quotedString();
+ skipWhitespace();
+ if (ch == '@'
+ || ch == EOI && bp == buf.length - 1) {
+ return;
+ }
+ break;
+
+ case '<':
+ blockContent();
+ return;
+
+ case '@':
+ if (newline)
+ throw new ParseException("dc.no.content");
+ break;
+
+ case EOI:
+ if (bp == buf.length - 1)
+ throw new ParseException("dc.no.content");
+ break;
+
+ default:
+ if (isJavaIdentifierStart(ch) || ch == '#') {
+ reference(true);
+ blockContent();
+ }
+ }
+ throw new ParseException("dc.unexpected.content");
+ }
+ },
+
+ // @serialData data-description
+ new TagParser(Kind.BLOCK, "@serialData") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // @serialField field-name field-type description
+ new TagParser(Kind.BLOCK, "serialField") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ skipWhitespace();
+ identifier();
+ skipWhitespace();
+ reference(false);
+ if (isWhitespace(ch)) {
+ skipWhitespace();
+ blockContent();
+ }
+ }
+ },
+
+ // @serial field-description | include | exclude
+ new TagParser(Kind.BLOCK, "serial") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // @since since-text
+ new TagParser(Kind.BLOCK, "since") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+
+ // @throws class-name description
+ new TagParser(Kind.BLOCK, "throws") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ skipWhitespace();
+ reference(false);
+ blockContent();
+ }
+ },
+
+ // {@value package.class#field}
+ new TagParser(Kind.INLINE, "value") {
+ @Override
+ public void parse(int pos) throws ParseException {
+ reference(true);
+ skipWhitespace();
+ if (ch == '}') {
+ nextChar();
+ return;
+ }
+ nextChar();
+ throw new ParseException("dc.unexpected.content");
+ }
+ },
+
+ // @version version-text
+ new TagParser(Kind.BLOCK, "version") {
+ @Override
+ public void parse(int pos) {
+ blockContent();
+ }
+ },
+ };
+
+ tagParsers = new HashMap<>();
+ for (TagParser p: parsers)
+ tagParsers.put(p.getName(), p);
+
+ }
+
+ private void initEventAttrs() {
+ eventAttrs = new HashSet<>(Arrays.asList(
+ // See https://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.event-handler
+ "onabort", "onblur", "oncanplay", "oncanplaythrough",
+ "onchange", "onclick", "oncontextmenu", "ondblclick",
+ "ondrag", "ondragend", "ondragenter", "ondragleave",
+ "ondragover", "ondragstart", "ondrop", "ondurationchange",
+ "onemptied", "onended", "onerror", "onfocus", "oninput",
+ "oninvalid", "onkeydown", "onkeypress", "onkeyup",
+ "onload", "onloadeddata", "onloadedmetadata", "onloadstart",
+ "onmousedown", "onmousemove", "onmouseout", "onmouseover",
+ "onmouseup", "onmousewheel", "onpause", "onplay",
+ "onplaying", "onprogress", "onratechange", "onreadystatechange",
+ "onreset", "onscroll", "onseeked", "onseeking",
+ "onselect", "onshow", "onstalled", "onsubmit", "onsuspend",
+ "ontimeupdate", "onvolumechange", "onwaiting",
+
+ // See https://www.w3.org/TR/html4/sgml/dtd.html
+ // Most of the attributes that take a %Script are also defined as event handlers
+ // in HTML 5. The one exception is onunload.
+ // "onchange", "onclick", "ondblclick", "onfocus",
+ // "onkeydown", "onkeypress", "onkeyup", "onload",
+ // "onmousedown", "onmousemove", "onmouseout", "onmouseover",
+ // "onmouseup", "onreset", "onselect", "onsubmit",
+ "onunload"
+ ));
+ }
+
+ private void initURIAttrs() {
+ uriAttrs = new HashSet<>(Arrays.asList(
+ // See https://www.w3.org/TR/html4/sgml/dtd.html
+ // https://www.w3.org/TR/html5/
+ // These are all the attributes that take a %URI or a valid URL potentially surrounded
+ // by spaces
+ "action", "cite", "classid", "codebase", "data",
+ "datasrc", "for", "href", "longdesc", "profile",
+ "src", "usemap"
+ ));
+ }
+
+}
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
index 678557b..ab7c272 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -381,6 +381,10 @@ public class RootDocImpl extends DocImpl implements RootDoc {
env.initDoclint(opts, customTagNames);
}
+ public JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
+ return env.initJavaScriptScanner(allowScriptInComments);
+ }
+
public boolean isFunctionalInterface(AnnotationDesc annotationDesc) {
return annotationDesc.annotationType().qualifiedName().equals(
env.syms.functionalInterfaceType.toString()) && env.source.allowLambda();
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
index 8ac2c34..adf73c6 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -110,6 +110,8 @@ javadoc.File_Read_Error=Error while reading file {0}
javadoc.Body_missing_from_html_file=Body tag missing from HTML file
javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file
javadoc.Multiple_package_comments=Multiple sources of package comments found for package "{0}"
+javadoc.JavaScript_in_comment=JavaScript found in documentation comment.\n\
+ Use --allow-script-in-comments to allow use of JavaScript.
javadoc.class_not_found=Class {0} not found.
javadoc.error=error
javadoc.warning=warning
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties
index 1c5f3f7..b71ca8d 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,7 @@ javadoc.File_Read_Error=\u30D5\u30A1\u30A4\u30EB{0}\u306E\u8AAD\u8FBC\u307F\u4E2
javadoc.Body_missing_from_html_file=HTML\u306Bbody\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093
javadoc.End_body_missing_from_html_file=HTML\u30D5\u30A1\u30A4\u30EB\u306Bbody\u306E\u9589\u3058\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093
javadoc.Multiple_package_comments=\u30D1\u30C3\u30B1\u30FC\u30B8"{0}"\u306B\u8907\u6570\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30B3\u30E1\u30F3\u30C8\u306E\u30BD\u30FC\u30B9\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F
+javadoc.JavaScript_in_comment=\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8\u306BJavaScript\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\n--allow-script-in-comments\u3092\u4F7F\u7528\u3057\u3066\u3001JavaScript\u306E\u4F7F\u7528\u3092\u8A31\u53EF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
javadoc.class_not_found=\u30AF\u30E9\u30B9{0}\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
javadoc.error=\u30A8\u30E9\u30FC
javadoc.warning=\u8B66\u544A
diff --git a/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties b/openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties
index 591f577..2f6d5ce 100644
--- openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties
+++ openjdk/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,7 @@ javadoc.File_Read_Error=\u8BFB\u53D6\u6587\u4EF6{0}\u65F6\u51FA\u9519
javadoc.Body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u6807\u8BB0
javadoc.End_body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u7ED3\u675F\u6807\u8BB0
javadoc.Multiple_package_comments=\u627E\u5230\u7A0B\u5E8F\u5305 "{0}" \u7684\u591A\u4E2A\u7A0B\u5E8F\u5305\u6CE8\u91CA\u6E90
+javadoc.JavaScript_in_comment=\u6587\u6863\u6CE8\u91CA\u4E2D\u53D1\u73B0 JavaScript\u3002\n\u4F7F\u7528 --allow-script-in-comments \u53EF\u5141\u8BB8\u4F7F\u7528 JavaScript\u3002
javadoc.class_not_found=\u627E\u4E0D\u5230\u7C7B{0}\u3002
javadoc.error=\u9519\u8BEF
javadoc.warning=\u8B66\u544A
diff --git a/openjdk/langtools/test/tools/doclint/html/OtherTagsTest.out b/openjdk/langtools/test/tools/doclint/html/OtherTagsTest.out
index 3fbcb15..5cd00fc 100644
--- openjdk/langtools/test/tools/doclint/html/OtherTagsTest.out
+++ openjdk/langtools/test/tools/doclint/html/OtherTagsTest.out
@@ -19,10 +19,7 @@ OtherTagsTest.java:19: error: element not allowed in documentation comments: <me
OtherTagsTest.java:20: error: element not allowed in documentation comments: <noframes>
* <noframes> </noframes>
^
-OtherTagsTest.java:21: error: element not allowed in documentation comments: <script>
- * <script> </script>
- ^
OtherTagsTest.java:22: error: element not allowed in documentation comments: <title>
* <title> </title>
^
-9 errors
+8 errors
diff --git a/openjdk/langtools/test/tools/javadoc/TestScriptInComment.java b/openjdk/langtools/test/tools/javadoc/TestScriptInComment.java
new file mode 100644
index 0000000..bda3aca
--- /dev/null
+++ openjdk/langtools/test/tools/javadoc/TestScriptInComment.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8138725
+ * @summary test --allow-script-in-comments
+ * @run main TestScriptInComment
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Combo-style test, exercising combinations of different HTML fragments that may contain
+ * JavaScript, different places to place those fragments, and whether or not to allow the use
+ * of JavaScript.
+ */
+public class TestScriptInComment {
+ public static void main(String... args) throws Exception {
+ new TestScriptInComment().run();
+ }
+
+ /**
+ * Representative samples of different fragments of HTML that may contain JavaScript.
+ * To facilitate checking the output manually in a browser, the text "#ALERT" will be
+ * replaced by a JavaScript call of "alert(msg)", using a message string that is specific
+ * to the test case.
+ */
+ enum Comment {
+ LC("<script>#ALERT</script>", true), // script tag in Lower Case
+ UC("<SCRIPT>#ALERT</script>", true), // script tag in Upper Case
+ WS("< script >#ALERT</script>", false, "-Xdoclint:none"), // script tag with invalid white space
+ SA("<script src=\"file\"> #ALERT </script>", true), // script tag with an attribute
+ ON("<a onclick='#ALERT'>x</a>", true), // event handler attribute
+ URI("<a href='javascript:#ALERT'>x</a>", true); // javadcript URI
+
+ /**
+ * Creates an HTML fragment to be injected into a template.
+ * @param text the HTML fragment to put into a doc comment or option.
+ * @param hasScript whether or not this fragment does contain legal JavaScript
+ * @param opts any additional options to be specified when javadoc is run
+ */
+ Comment(String text, boolean hasScript, String... opts) {
+ this.text = text;
+ this.hasScript = hasScript;
+ this.opts = Arrays.asList(opts);
+ }
+
+ final String text;
+ final boolean hasScript;
+ final List<String> opts;
+ };
+
+ /**
+ * Representative samples of positions in which javadoc may find JavaScript.
+ * Each template contains a series of strings, which are written to files or inferred as options.
+ * The first source file implies a corresponding output file which should not be written
+ * if the comment contains JavaScript and JavaScript is not allowed.
+ */
+ enum Template {
+ OVR("<html><body> overview #COMMENT </body></html>", "package p; public class C { }"),
+ PKGINFO("#COMMENT package p;", "package p; public class C { }"),
+ PKGHTML("<html><body>#COMMENT package p;</body></html>", "package p; public class C { }"),
+ CLS("package p; #COMMENT public class C { }"),
+ CON("package p; public class C { #COMMENT public C() { } }"),
+ FLD("package p; public class C { #COMMENT public int f; }"),
+ MTH("package p; public class C { #COMMENT public void m() { } }"),
+ TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"),
+ HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"),
+ FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"),
+ BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"),
+ DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"),
+ PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }");
+
+ Template(String... args) {
+ opts = new ArrayList<String>();
+ sources = new ArrayList<String>();
+ int i = 0;
+ while (args[i].startsWith("-")) {
+ // all options being tested have a single argument that follow the option
+ opts.add(args[i++]);
+ opts.add(args[i++]);
+ }
+ while(i < args.length) {
+ sources.add(args[i++]);
+ }
+ }
+
+ // groups: 1 <html> or not; 2: package name; 3: class name
+ private final Pattern pat =
+ Pattern.compile("(?i)(<html>)?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?");
+
+ /**
+ * Infer the file in which to write the given source.
+ * @param dir the base source directory
+ * @param src the source text
+ * @return the file in which the source should be written
+ */
+ File getSrcFile(File srcDir, String src) {
+ String f;
+ Matcher m = pat.matcher(src);
+ if (!m.matches())
+ throw new Error("match failed");
+ if (m.group(3) != null) {
+ f = m.group(2) + "/" + m.group(3) + ".java";
+ } else if (m.group(2) != null) {
+ f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html");
+ } else {
+ f = "overview.html";
+ }
+ return new File(srcDir, f);
+ }
+
+ /**
+ * Get the options to give to javadoc.
+ * @param srcDir the srcDir to use -overview is needed
+ * @return
+ */
+ List<String> getOpts(File srcDir) {
+ if (!opts.isEmpty()) {
+ return opts;
+ } else if (sources.get(0).contains("overview")) {
+ return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath());
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * Gets the output file corresponding to the first source file.
+ * This file should not be written if the comment contains JavaScript and JavaScripot is
+ * not allowed.
+ * @param dir the base output directory
+ * @return the output file
+ */
+ File getOutFile(File outDir) {
+ String f;
+ Matcher m = pat.matcher(sources.get(0));
+ if (!m.matches())
+ throw new Error("match failed");
+ if (m.group(3) != null) {
+ f = m.group(2) + "/" + m.group(3) + ".html";
+ } else if (m.group(2) != null) {
+ f = m.group(2) + "/package-summary.html";
+ } else {
+ f = "overview-summary.html";
+ }
+ return new File(outDir, f);
+ }
+
+ final List<String> opts;
+ final List<String> sources;
+ };
+
+ enum Option {
+ OFF(null),
+ ON("--allow-script-in-comments");
+
+ Option(String text) {
+ this.text = text;
+ }
+
+ final String text;
+ };
+
+ private PrintStream out = System.err;
+
+ public void run() throws Exception {
+ int count = 0;
+ for (Template template: Template.values()) {
+ for (Comment comment: Comment.values()) {
+ for (Option option: Option.values()) {
+ if (test(template, comment, option)) {
+ count++;
+ }
+ }
+ }
+ }
+
+ out.println(count + " test cases run");
+ if (errors > 0) {
+ throw new Exception(errors + " errors occurred");
+ }
+ }
+
+ boolean test(Template template, Comment comment, Option option) throws IOException {
+ if (option == Option.ON && !comment.hasScript) {
+ // skip --allowScriptInComments if comment does not contain JavaScript
+ return false;
+ }
+
+ String test = template + "-" + comment + "-" + option;
+ out.println("Test: " + test);
+
+ File dir = new File(test);
+ dir.mkdirs();
+ File srcDir = new File(dir, "src");
+ File outDir = new File(dir, "out");
+
+ String alert = "alert(\"" + test + "\");";
+ for (String src: template.sources) {
+ writeFile(template.getSrcFile(srcDir, src),
+ src.replace("#COMMENT",
+ "/** " + comment.text.replace("#ALERT", alert) + " **/"));
+ }
+
+ List<String> opts = new ArrayList<String>();
+ opts.add("-sourcepath");
+ opts.add(srcDir.getPath());
+ opts.add("-d");
+ opts.add(outDir.getPath());
+ if (option.text != null)
+ opts.add(option.text);
+ for (String opt: template.getOpts(srcDir)) {
+ opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert)));
+ }
+ opts.addAll(comment.opts);
+ opts.add("-noindex"); // index not required; save time/space writing files
+ opts.add("p");
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ int rc = javadoc(opts, pw);
+ pw.close();
+ String log = sw.toString();
+ writeFile(new File(dir, "log.txt"), log);
+
+ out.println("opts: " + opts);
+ out.println(" rc: " + rc);
+ out.println(" log:");
+ out.println(log);
+
+ String ERROR = "Use --allow-script-in-comment";
+ File outFile = template.getOutFile(outDir);
+
+ boolean expectErrors = comment.hasScript && (option == Option.OFF);
+
+ if (expectErrors) {
+ check(rc != 0, "unexpected exit code: " + rc);
+ check(log.contains(ERROR), "expected error message not found");
+ check(!outFile.exists(), "output file found unexpectedly");
+ } else {
+ check(rc == 0, "unexpected exit code: " + rc);
+ check(!log.contains(ERROR), "error message found");
+ check(outFile.exists(), "output file not found");
+ }
+
+ out.println();
+ return true;
+ }
+
+ int javadoc(List<String> opts, PrintWriter pw) {
+ return com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw,
+ "com.sun.tools.doclets.standard.Standard", opts.toArray(new String[opts.size()]));
+ }
+
+ File writeFile(File f, String text) throws IOException {
+ f.getParentFile().mkdirs();
+ FileWriter fw = new FileWriter(f);
+ try {
+ fw.write(text);
+ } finally {
+ fw.close();
+ }
+ return f;
+ }
+
+ void check(boolean cond, String errMessage) {
+ if (!cond) {
+ error(errMessage);
+ }
+ }
+
+ void error(String message) {
+ out.println("Error: " + message);
+ errors++;
+ }
+
+ int errors = 0;
+}
+