Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4027524

NewStringUTF doesn't check correctness its UTF8 string argument

XMLWordPrintable

    • sparc
    • solaris_2.5



      Name: laC46010 Date: 01/23/97



      JNI spec says:

      "There are two differences between this format and the "standard" UTF-8
      format. First, the null byte (byte)0 is encoded using the two-byte
      format rather than the one-byte format. This means that Java VM UTF-8
      strings never have embedded nulls. Second, only the one-byte, two-byte,
      and three-byte formats are used. The Java VM does not recognize the
      longer UTF-8 formats."

      UTF8 format described doesn't allow UTF8 string to contain 0xf0-0xff as first
      bytes of the format. However NewStringUTF() doesn't check correctness of UTF8
      strings and accept strings containing "wrong" bytes. See the test below.

      The test creates byte array that contains wrong bytes
      using native method "putChar". The line
      *(carr+acount) = 0xf0 + (acount-acount/2);
      adds such wrong bytes. Then this array is converted to string in
      the native method "fromArray" using NewStringUTF().

      To run the test, set environment variables JH (Java home) and CC (C compiler)
      and run "jnirun" script.

      >jnirun
      Bytes in Array: 31 f1 32 f2 33 f3 34 f4 35 f5 36 f6 37 f7 38 f8 39 f9 61 fa 62 fb 63 fc 64 fd 65 fe 66 ff
      Create string with invalid UTF-8:1?2?3?4?5?6?7?8?9?a?b?c?d?e?f?
      Chars of the new string:
       31 fff1 32 fff2 33 fff3 34 fff4 35 fff5 36 fff6 37 fff7 38 fff8 39 fff9 61 fffa 62 fffb 63 fffc 64 fffd 65 fffe 66 ffff

      ::::::::::::::
      jnirun
      ::::::::::::::
      #!/usr/bin/csh

      #setenv JH /export/ld32/dest/jdk1.1beta3/solaris
      #setenv CC /export/ld4/set/dist/sparc-S2/SC4.2/bin/cc

      $JH/bin/javac -d . *[1-9].java
      $CC -KPIC -G -I$JH/include -I$JH/include/solaris -o libtest.so *.c
      setenv LD_LIBRARY_PATH ".:$LD_LIBRARY_PATH"
      setenv CLASSPATH .
      $JH/bin/java javasoft.sqe.tests.vm.nstu2.nstu2.nstu00102
      ::::::::::::::
      nstu00102.c
      ::::::::::::::
      /* File: %Z%%M% %I% %E%
         Copyright %G% Sun Microsystems, Inc. All Rights Reserved
      */

      #include <stdio.h>
      #include "native.h"

      #ifdef __cplusplus
      extern "C" {
      #endif

      #ifdef __cplusplus
      #define JNI_ENV_ARG(x,y) y
      #define JNI_ENV_PTR(x) x
      #else
      #define JNI_ENV_ARG(x,y) x,y
      #define JNI_ENV_PTR(x) (*x)
      #endif

      jbyte * carr;
      int alen, acount, acounts;


      JNIEXPORT jstring JNICALL
      Java_javasoft_sqe_tests_vm_nstu2_nstu2_nstu00102_nstu00102fromArray
      (JNIEnv *env, jobject obj) {
      int i;
      printf("Bytes in Array:");
      for (i=0;i < acount;i++) {
      printf(" %x",*(carr+i)&0xff);
      }
      printf("\n");
      return (JNI_ENV_PTR(env) -> NewStringUTF(JNI_ENV_ARG(env, carr), acounts ));
      }

      JNIEXPORT jboolean JNICALL
      Java_javasoft_sqe_tests_vm_nstu2_nstu2_nstu00102_nstu00102createArray
      (JNIEnv *env, jobject obj, jsize len) {
      carr = malloc(len * 3);
      alen = len;
      acount = 0;
      acounts = 0;
      return ((carr == NULL)?JNI_FALSE:JNI_TRUE);
      }

      JNIEXPORT jboolean JNICALL
      Java_javasoft_sqe_tests_vm_nstu2_nstu2_nstu00102_nstu00102putChar
      (JNIEnv *env, jobject obj, jchar ch) {
      jbyte curb;
      if (acounts >= alen*3)
      return JNI_FALSE;
      if (ch == 0) {
      curb = 0xc0;
      *(carr+acount) = curb & 0xff;
      acount++;
      curb = 0x80;
      *(carr+acount) = curb & 0xff;
      }
      else {
      if ( ch <= 0x7f) {
      curb = (jbyte) ch;
      *(carr+acount) = curb & 0xff;
      }
      if ( (ch >= 0x80) && (ch <= 0x7ff) ) {
      curb = (0x6<<5) | (( ch & 0x7c0) >> 6);
      *(carr+acount) = curb & 0xff;
      acount++;
      curb = (0x2<<6) | ( ch & 0x3f) ;
      *(carr+acount) = curb & 0xff;
      }
      if ( ch >= 0x800 ) {
      curb = (0xe<<4) | (( ch & 0xf000) >> 12);
      *(carr+acount) = curb & 0xff;
      acount++;
      curb = (0x2<<6) | ((ch & 0xfc0) >> 6);
      *(carr+acount) = curb & 0xff;
      curb = (0x2<<6) | (ch & 0x3f);
      acount++;
      *(carr+acount) = curb & 0xff;
      }
      }
      acount++;
      *(carr+acount) = 0xf0 + (acount-acount/2);
      acount++;
      acounts++;
      acounts++;
      return JNI_TRUE;
      }
      #ifdef __cplusplus
      }
      #endif
      ::::::::::::::
      nstu00102.java
      ::::::::::::::
      //File: %Z%%M% %I% %E%
      //Copyright %G% Sun Microsystems, Inc. All Rights Reserved

      package javasoft.sqe.tests.vm.nstu2.nstu2;
      import java.io.PrintStream;


      public class nstu00102 {

        public static void main(String argv[])
        {
           System.exit(run() + 95/*STATUS_TEMP*/);
        }

        public native String nstu00102fromArray();
        public native boolean nstu00102createArray(int len);
        public native boolean nstu00102putChar(char val);

        static {
          System.loadLibrary("test");
        }
        static void printStrHex (String ss) {
          int i;
          int val;
          for (i=0; i < ss.length(); i ++) {
            val = ss.charAt(i);
            System.out.print(" ");
            System.out.print(Integer.toHexString(val));
          }
          System.out.println(" ");
        }
        
        static String str1 = new String("123456789abcdef");
        
        public static int run() {
          nstu00102 tob = new nstu00102();
          boolean res = false;
          String lstr = new String("");
          int i;
          try {
            if (!tob.nstu00102createArray(str1.length())) {
            res = true;
            System.out.println("Cannot create array in nstu00102createArray");
            return 2;
            }
            for (i=0; i < str1.length(); i++) {
              if (!tob.nstu00102putChar(str1.charAt(i))) {
                res = true;
                System.out.println("Cannot putChar in nstu00102createArray:" + i);
              }
            }
            lstr = tob.nstu00102fromArray();
          } catch (Throwable e) {
            res = true;
            System.out.println("Exception caught: " + e);
          }
          if (lstr != null) {
            res = true;
            System.out.println("Create string with invalid UTF-8:" + lstr);
            System.out.println("Chars of the new string:");
            printStrHex (lstr);
          }
          if (res)
            return 2/*STATUS_FAILED*/;
          return 0/*STATUS_PASSED*/;
        }
      }

      ======================================================================

            sliangsunw Sheng Liang (Inactive)
            leosunw Leo Leo (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: