1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import java.io.IOException; 11 12 /** 13 * Thrown when a protocol message being parsed is invalid in some way. For instance, 14 * it contains a malformed varint or a negative byte length. 15 * 16 * @author kenton@google.com Kenton Varda 17 */ 18 public class InvalidProtocolBufferException extends IOException { 19 private static final long serialVersionUID = -1616151763072450476L; 20 private MessageLite unfinishedMessage = null; 21 private boolean wasThrownFromInputStream; 22 InvalidProtocolBufferException(String description)23 public InvalidProtocolBufferException(String description) { 24 super(description); 25 } 26 InvalidProtocolBufferException(Exception e)27 public InvalidProtocolBufferException(Exception e) { 28 super(e.getMessage(), e); 29 } 30 InvalidProtocolBufferException(String description, Exception e)31 public InvalidProtocolBufferException(String description, Exception e) { 32 super(description, e); 33 } 34 InvalidProtocolBufferException(IOException e)35 public InvalidProtocolBufferException(IOException e) { 36 super(e.getMessage(), e); 37 } 38 InvalidProtocolBufferException(String description, IOException e)39 public InvalidProtocolBufferException(String description, IOException e) { 40 super(description, e); 41 } 42 43 /** 44 * Attaches an unfinished message to the exception to support best-effort parsing in {@code 45 * Parser} interface. 46 * 47 * @return this 48 */ setUnfinishedMessage(MessageLite unfinishedMessage)49 public InvalidProtocolBufferException setUnfinishedMessage(MessageLite unfinishedMessage) { 50 this.unfinishedMessage = unfinishedMessage; 51 return this; 52 } 53 54 /** 55 * Returns the unfinished message attached to the exception, or null if no message is attached. 56 */ getUnfinishedMessage()57 public MessageLite getUnfinishedMessage() { 58 return unfinishedMessage; 59 } 60 61 /** Set by CodedInputStream */ setThrownFromInputStream()62 void setThrownFromInputStream() { 63 /* This write can be racy if the same exception is stored and then thrown by multiple custom 64 * InputStreams on different threads. But since it only ever moves from false->true, there's no 65 * problem. A thread checking this condition after catching this exception from a delegate 66 * stream of CodedInputStream is guaranteed to always observe true, because a write on the same 67 * thread set the value when the exception left the delegate. A thread checking the same 68 * condition with an exception created by CodedInputStream is guaranteed to always see false, 69 * because the exception has not been exposed to any code that could publish it to other threads 70 * and cause a write. 71 */ 72 wasThrownFromInputStream = true; 73 } 74 75 /** 76 * Allows code catching IOException from CodedInputStream to tell whether this instance was thrown 77 * by a delegate InputStream, rather than directly by a parse failure. 78 */ getThrownFromInputStream()79 boolean getThrownFromInputStream() { 80 return wasThrownFromInputStream; 81 } 82 83 /** 84 * Unwraps the underlying {@link IOException} if this exception was caused by an I/O problem. 85 * Otherwise, returns {@code this}. 86 */ unwrapIOException()87 public IOException unwrapIOException() { 88 return getCause() instanceof IOException ? (IOException) getCause() : this; 89 } 90 truncatedMessage()91 static InvalidProtocolBufferException truncatedMessage() { 92 return new InvalidProtocolBufferException( 93 "While parsing a protocol message, the input ended unexpectedly " 94 + "in the middle of a field. This could mean either that the " 95 + "input has been truncated or that an embedded message " 96 + "misreported its own length."); 97 } 98 negativeSize()99 static InvalidProtocolBufferException negativeSize() { 100 return new InvalidProtocolBufferException( 101 "CodedInputStream encountered an embedded string or message " 102 + "which claimed to have negative size."); 103 } 104 malformedVarint()105 static InvalidProtocolBufferException malformedVarint() { 106 return new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint."); 107 } 108 invalidTag()109 static InvalidProtocolBufferException invalidTag() { 110 return new InvalidProtocolBufferException("Protocol message contained an invalid tag (zero)."); 111 } 112 invalidEndTag()113 static InvalidProtocolBufferException invalidEndTag() { 114 return new InvalidProtocolBufferException( 115 "Protocol message end-group tag did not match expected tag."); 116 } 117 invalidWireType()118 static InvalidWireTypeException invalidWireType() { 119 return new InvalidWireTypeException("Protocol message tag had invalid wire type."); 120 } 121 122 /** Exception indicating that an unexpected wire type was encountered for a field. */ 123 @ExperimentalApi 124 public static class InvalidWireTypeException extends InvalidProtocolBufferException { 125 private static final long serialVersionUID = 3283890091615336259L; 126 InvalidWireTypeException(String description)127 public InvalidWireTypeException(String description) { 128 super(description); 129 } 130 } 131 recursionLimitExceeded()132 static InvalidProtocolBufferException recursionLimitExceeded() { 133 return new InvalidProtocolBufferException( 134 "Protocol message had too many levels of nesting. May be malicious. " 135 + "Use setRecursionLimit() to increase the recursion depth limit."); 136 } 137 sizeLimitExceeded()138 static InvalidProtocolBufferException sizeLimitExceeded() { 139 return new InvalidProtocolBufferException( 140 "Protocol message was too large. May be malicious. " 141 + "Use CodedInputStream.setSizeLimit() to increase the size limit."); 142 } 143 parseFailure()144 static InvalidProtocolBufferException parseFailure() { 145 return new InvalidProtocolBufferException("Failed to parse the message."); 146 } 147 invalidUtf8()148 static InvalidProtocolBufferException invalidUtf8() { 149 return new InvalidProtocolBufferException("Protocol message had invalid UTF-8."); 150 } 151 } 152