Commits

Rhys !  committed d6037bf Draft

prevent users from encoding a tuple with 'bert in position 0

  • Participants
  • Parent commits df62ddf

Comments (0)

Files changed (3)

File src/org/bert_rpc/Bert.java

     public static byte[] encode(Object value) throws EncodingException {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         try {
-            new Encoder(out).encodeObject(value);
+            new Encoder(out).encodeUnknownType(value);
             out.flush();
         } catch (IOException e) {
             throw new RuntimeException("Writing to array failed somehow: "

File src/org/bert_rpc/Encoder.java

         this.outputStream = new DataOutputStream(outputStream);
     }
 
-    public void encodeObject(Object object)
+    public void encodeUnknownType(Object object)
             throws IOException, EncodingException {
         this.outputStream.writeByte(Constants.MAGIC);
         this.writeUnknownType(object);
     }
 
     @SuppressWarnings("unchecked") // for Map to Map<K, V> cast
-    private void writeUnknownType(Object value)
+    public void writeUnknownType(Object value)
             throws EncodingException, IOException {
         if (value == null) {
             this.writeNull();
         this.outputStream.flush();
     }
 
+    /**
+     * Write a tuple that is user-provided and cannot be a complex type.
+     *
+     * @param tuple The tuple to write.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
     private void writeTuple(Tuple tuple)
             throws IOException, EncodingException {
+        if (tuple.size() > 0 && Constants.$bert.equals(tuple.get(0))) {
+            throw new EncodingException(
+                    "tuple cannot have atom 'bert in position 0.");
+        } else {
+            this.writeComplexTuple(tuple);
+        }
+    }
+
+    /**
+     * Write a tuple that may be a complex type.
+     *
+     * @param tuple The tuple to write.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
+    private void writeComplexTuple(Tuple tuple)
+            throws IOException, EncodingException {
         if (tuple.size() < 256) {
             this.outputStream.write(Constants.SMALL_TUPLE);
             this.outputStream.writeByte(tuple.size());
             pairs.add(new Tuple(o.getKey(), o.getValue()));
         }
 
-        this.writeTuple(new Tuple(Constants.$bert, Constants.$dict, pairs));
+        this.writeComplexTuple(
+                new Tuple(Constants.$bert, Constants.$dict, pairs));
     }
 
     public void encode(Date date) throws IOException {
         long millis = date.getTime();
 
         try {
-            this.writeTuple(new Tuple(Constants.$bert, Constants.$time,
+            this.writeComplexTuple(new Tuple(Constants.$bert, Constants.$time,
                     (int) Math.floor(millis / 1e9),
                     (int) Math.floor((millis % 1e9) / 1e3),
                     (int) Math.floor(millis % 1e3)));
         }
 
         try {
-            this.writeTuple(new Tuple(Constants.$bert, representation));
+            this.writeComplexTuple(new Tuple(Constants.$bert, representation));
         } catch (EncodingException e) {
             throw new RuntimeException("somehow failed to encode boolean (" +
                     e.getMessage() + "). this is a bug in jbert.", e);
 
     private void writeNull() throws IOException {
         try {
-            this.writeTuple(new Tuple(Constants.$bert, Constants.$nil));
+            this.writeComplexTuple(new Tuple(Constants.$bert, Constants.$nil));
         } catch (EncodingException e) {
             throw new RuntimeException(
                     "somehow failed to encode null (" + e.getMessage() +
         }
 
         try {
-            this.writeTuple(new Tuple(Constants.$bert, Constants.$regex,
+            this.writeComplexTuple(new Tuple(Constants.$bert, Constants.$regex,
                     regex.pattern().getBytes("UTF8"),
                     flags));
         } catch (EncodingException e) {

File test/src/org/bert_rpc/TestEncoder.java

                 Bert.encode(new Tuple(new Atom("foo"), new Atom("bar"))));
     }
 
+    @Test(expected = EncodingException.class)
+    public void testDisallowsBertAtomFirst() throws Exception {
+        Bert.encode(new Tuple(new Atom("bert"), new Atom("foo")));
+    }
+
     @Test
     public void testEncodesFloats() throws Exception {
         Assert.assertArrayEquals("encodes floats",