From d92ca7dcea105837e3e576f797501c19929eced5 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Tue, 18 Mar 2008 19:32:00 +0000 Subject: [PATCH] Prevent Java's TProtocolUtil.skip from overflowing the stack. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665577 13f79535-47bb-0310-9956-ffa450edef68 --- lib/java/src/protocol/TProtocolUtil.java | 54 +++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/lib/java/src/protocol/TProtocolUtil.java b/lib/java/src/protocol/TProtocolUtil.java index 5c665ab0..dc4aeebd 100644 --- a/lib/java/src/protocol/TProtocolUtil.java +++ b/lib/java/src/protocol/TProtocolUtil.java @@ -7,7 +7,6 @@ package com.facebook.thrift.protocol; import com.facebook.thrift.TException; -import com.facebook.thrift.transport.TTransport; /** * Utility class with static methods for interacting with protocol data @@ -16,9 +15,52 @@ import com.facebook.thrift.transport.TTransport; * @author Mark Slee */ public class TProtocolUtil { + + /** + * The maximum recursive depth the skip() function will traverse before + * throwing a TException. + */ + private static int maxSkipDepth = Integer.MAX_VALUE; + + /** + * Specifies the maximum recursive depth that the skip function will + * traverse before throwing a TException. This is a global setting, so + * any call to skip in this JVM will enforce this value. + * + * @param depth the maximum recursive depth. A value of 2 would allow + * the skip function to skip a structure or collection with basic children, + * but it would not permit skipping a struct that had a field containing + * a child struct. A value of 1 would only allow skipping of simple + * types and empty structs/collections. + */ + public static void setMaxSkipDepth(int depth) { + maxSkipDepth = depth; + } + + /** + * Skips over the next data element from the provided input TProtocol object. + * + * @param prot the protocol object to read from + * @param type the next value will be intepreted as this TType value. + */ public static void skip(TProtocol prot, byte type) throws TException { + skip(prot, type, maxSkipDepth); + } + /** + * Skips over the next data element from the provided input TProtocol object. + * + * @param prot the protocol object to read from + * @param type the next value will be intepreted as this TType value. + * @param maxDepth this function will only skip complex objects to this + * recursive depth, to prevent Java stack overflow. + */ + public static void skip(TProtocol prot, byte type, int maxDepth) + throws TException { + if (maxDepth <= 0) { + throw new TException("Maximum skip depth exceeded"); + } switch (type) { case TType.BOOL: { @@ -63,7 +105,7 @@ public class TProtocolUtil { if (field.type == TType.STOP) { break; } - skip(prot, field.type); + skip(prot, field.type, maxDepth - 1); prot.readFieldEnd(); } prot.readStructEnd(); @@ -73,8 +115,8 @@ public class TProtocolUtil { { TMap map = prot.readMapBegin(); for (int i = 0; i < map.size; i++) { - skip(prot, map.keyType); - skip(prot, map.valueType); + skip(prot, map.keyType, maxDepth - 1); + skip(prot, map.valueType, maxDepth - 1); } prot.readMapEnd(); break; @@ -83,7 +125,7 @@ public class TProtocolUtil { { TSet set = prot.readSetBegin(); for (int i = 0; i < set.size; i++) { - skip(prot, set.elemType); + skip(prot, set.elemType, maxDepth - 1); } prot.readSetEnd(); break; @@ -92,7 +134,7 @@ public class TProtocolUtil { { TList list = prot.readListBegin(); for (int i = 0; i < list.size; i++) { - skip(prot, list.elemType); + skip(prot, list.elemType, maxDepth - 1); } prot.readListEnd(); break; -- 2.17.1