Bug 536681 - [ZipSlip] ArchiveSourceContainer can create ZipEntryStorage
objects containing unintended entries

Change-Id: I2aa47ef66f92852671fbf0330056ac5516116693
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/sourcelookup/containers/ExternalArchiveSourceContainer.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/sourcelookup/containers/ExternalArchiveSourceContainer.java
index ff2a563..1acefed 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/sourcelookup/containers/ExternalArchiveSourceContainer.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/sourcelookup/containers/ExternalArchiveSourceContainer.java
@@ -108,21 +108,32 @@
 				// search
 				Enumeration<? extends ZipEntry> entries = file.entries();
 				List<ZipEntryStorage> matches = null;
-				while (entries.hasMoreElements()) {
-					entry = entries.nextElement();
-					String entryName = entry.getName();
-					if (entryName.endsWith(newname)) {
-						if (isQualfied || entryName.length() == newname.length() || entryName.charAt(entryName.length() - newname.length() - 1) == '/') {
-							if (isFindDuplicates()) {
-								if (matches == null) {
-									matches = new ArrayList<>();
+				try {
+					File zipFile = new File(fArchivePath);
+					String zipFileCanonical = zipFile.getCanonicalPath();
+					while (entries.hasMoreElements()) {
+						entry = entries.nextElement();
+						String entryName = entry.getName();
+						if (entryName.endsWith(newname)) {
+							String zipEntryCanonical = (new File(zipFile, entryName)).getCanonicalPath();
+							if (!zipEntryCanonical.startsWith(zipFileCanonical + File.separator)) {
+								throw new CoreException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), "Invalid path: " + zipEntryCanonical)); //$NON-NLS-1$
+							}
+							if (isQualfied || entryName.length() == newname.length() || entryName.charAt(entryName.length() - newname.length() - 1) == '/') {
+								if (isFindDuplicates()) {
+									if (matches == null) {
+										matches = new ArrayList<>();
+									}
+									matches.add(new ZipEntryStorage(file, entry));
+								} else {
+									return new Object[] {
+											new ZipEntryStorage(file, entry) };
 								}
-								matches.add(new ZipEntryStorage(file, entry));
-							} else {
-								return new Object[]{new ZipEntryStorage(file, entry)};
 							}
 						}
 					}
+				} catch (IOException e) {
+					throw new CoreException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), "Invalid path: " + fArchivePath)); //$NON-NLS-1$
 				}
 				if (matches != null) {
 					return matches.toArray();