summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO27
-rw-r--r--.gitignore5
-rw-r--r--CVE-2011-4599.patch22
-rw-r--r--CVE-2013-0900.patch296
-rw-r--r--PKGBUILD68
-rw-r--r--fix-test.diff11
-rw-r--r--indic-ccmp.patch50
-rw-r--r--malayalam-rendering.patch166
-rw-r--r--mlym-crash.patch19
9 files changed, 664 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 00000000000..52ee0d8aa85
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,27 @@
+pkgbase = icu48
+ pkgdesc = International Components for Unicode library, version 4.8
+ pkgver = 4.8.1.1
+ pkgrel = 3
+ url = http://www.icu-project.org/
+ arch = i686
+ arch = x86_64
+ license = custom:"icu"
+ depends = gcc-libs>=4.7.1-5
+ depends = sh
+ source = http://download.icu-project.org/files/icu4c/4.8.1.1/icu4c-4_8_1_1-src.tgz
+ source = malayalam-rendering.patch
+ source = CVE-2011-4599.patch
+ source = indic-ccmp.patch
+ source = mlym-crash.patch
+ source = CVE-2013-0900.patch
+ source = fix-test.diff
+ md5sums = ea93970a0275be6b42f56953cd332c17
+ md5sums = 9581cfaccbf93b6d6f7f7644bebcdafa
+ md5sums = 835c9e3ae0b76aa88a6ce144a42a3bce
+ md5sums = 6602e6d9727376174cbb1b688e5e3325
+ md5sums = a6a9daa1e3655c5058148af8903a443b
+ md5sums = 9528996e1e2099bb79d25fbd799a511e
+ md5sums = 766a677946f50029e0c01f5b8d30afec
+
+pkgname = icu48
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000000..7e6fb660ca0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+pkg
+src
+*.tar.gz
+*.zip
+*.tar.xz
diff --git a/CVE-2011-4599.patch b/CVE-2011-4599.patch
new file mode 100644
index 00000000000..0eabb80ab8c
--- /dev/null
+++ b/CVE-2011-4599.patch
@@ -0,0 +1,22 @@
+Index: icu-4.8.1.1/source/common/uloc.c
+===================================================================
+--- icu-4.8.1.1.orig/source/common/uloc.c 2011-10-18 19:12:40.000000000 -0400
++++ icu-4.8.1.1/source/common/uloc.c 2012-01-21 19:42:18.087577138 -0500
+@@ -1797,7 +1797,7 @@
+ int32_t variantLen = _deleteVariant(variant, uprv_min(variantSize, (nameCapacity-len)), variantToCompare, n);
+ len -= variantLen;
+ if (variantLen > 0) {
+- if (name[len-1] == '_') { /* delete trailing '_' */
++ if (len > 0 && name[len-1] == '_') { /* delete trailing '_' */
+ --len;
+ }
+ addKeyword = VARIANT_MAP[j].keyword;
+@@ -1805,7 +1805,7 @@
+ break;
+ }
+ }
+- if (name[len-1] == '_') { /* delete trailing '_' */
++ if (len > 0 && len <= nameCapacity && name[len-1] == '_') { /* delete trailing '_' */
+ --len;
+ }
+ }
diff --git a/CVE-2013-0900.patch b/CVE-2013-0900.patch
new file mode 100644
index 00000000000..710d3e9d4a0
--- /dev/null
+++ b/CVE-2013-0900.patch
@@ -0,0 +1,296 @@
+Description: CVE-2013-0900: Race condition in ICU.
+ Credit to Google Chrome Security Team (Inferno)
+ Patch taken from backport done by Fedora 17
+Origin: upstream, http://www.icu-project.org/trac/changeset/32865, http://www.icu-project.org/trac/changeset/32908
+Bug-Debian: http://bugs.debian.org/702346
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2013-0900
+
+Index: icu-4.8.1.1/source/common/locid.cpp
+===================================================================
+--- icu-4.8.1.1.orig/source/common/locid.cpp 2013-03-21 11:21:45.053153118 -0400
++++ icu-4.8.1.1/source/common/locid.cpp 2013-03-21 11:21:45.029153121 -0400
+@@ -1,6 +1,6 @@
+ /*
+ **********************************************************************
+- * Copyright (C) 1997-2010, International Business Machines
++ * Copyright (C) 1997-2012, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ **********************************************************************
+ *
+@@ -32,6 +32,7 @@
+
+ #include "unicode/locid.h"
+ #include "unicode/uloc.h"
++#include "mutex.h"
+ #include "umutex.h"
+ #include "uassert.h"
+ #include "cmemory.h"
+@@ -41,6 +42,21 @@
+
+ #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
++U_CDECL_BEGIN
++static UBool U_CALLCONV locale_cleanup(void);
++U_CDECL_END
++
++U_NAMESPACE_BEGIN
++
++static U_NAMESPACE_QUALIFIER Locale *gLocaleCache = NULL;
++
++// gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
++static UMTX gDefaultLocaleMutex = 0;
++static UHashtable *gDefaultLocalesHashT = NULL;
++static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale = NULL;
++
++U_NAMESPACE_END
++
+ typedef enum ELocalePos {
+ eENGLISH,
+ eFRENCH,
+@@ -75,10 +91,6 @@
+ UBool valuesToo,
+ UErrorCode *status);
+
+-static U_NAMESPACE_QUALIFIER Locale *gLocaleCache = NULL;
+-static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale = NULL;
+-static UHashtable *gDefaultLocalesHashT = NULL;
+-
+ U_CDECL_BEGIN
+ //
+ // Deleter function for Locales owned by the default Locale hash table/
+@@ -100,24 +112,19 @@
+ if (gDefaultLocalesHashT) {
+ uhash_close(gDefaultLocalesHashT); // Automatically deletes all elements, using deleter func.
+ gDefaultLocalesHashT = NULL;
++ gDefaultLocale = NULL;
+ }
+- else if (gDefaultLocale) {
+- // The cache wasn't created, and only one default locale was created.
+- delete gDefaultLocale;
+- }
+- gDefaultLocale = NULL;
+
+ return TRUE;
+ }
+ U_CDECL_END
+
+ U_NAMESPACE_BEGIN
+-//
+-// locale_set_default_internal.
+-//
+-void locale_set_default_internal(const char *id)
+-{
+- UErrorCode status = U_ZERO_ERROR;
++
++Locale *locale_set_default_internal(const char *id, UErrorCode& status) {
++ // Synchronize this entire function.
++ Mutex lock(&gDefaultLocaleMutex);
++
+ UBool canonicalize = FALSE;
+
+ // If given a NULL string for the locale id, grab the default
+@@ -125,17 +132,10 @@
+ // (Different from most other locale APIs, where a null name means use
+ // the current ICU default locale.)
+ if (id == NULL) {
+- umtx_lock(NULL);
+- id = uprv_getDefaultLocaleID();
+- umtx_unlock(NULL);
++ id = uprv_getDefaultLocaleID(); // This function not thread safe? TODO: verify.
+ canonicalize = TRUE; // always canonicalize host ID
+ }
+
+- // put the locale id into a canonical form,
+- // in preparation for looking up this locale in the hash table of
+- // already-created locale objects.
+- //
+- status = U_ZERO_ERROR;
+ char localeNameBuf[512];
+
+ if (canonicalize) {
+@@ -146,100 +146,37 @@
+ localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of
+ // a long name filling the buffer.
+ // (long names are truncated.)
++ //
++ if (U_FAILURE(status)) {
++ return gDefaultLocale;
++ }
+
+- // Lazy creation of the hash table itself, if needed.
+- UBool isOnlyLocale;
+- UMTX_CHECK(NULL, (gDefaultLocale == NULL), isOnlyLocale);
+- if (isOnlyLocale) {
+- // We haven't seen this locale id before.
+- // Create a new Locale object for it.
+- Locale *newFirstDefault = new Locale(Locale::eBOGUS);
+- if (newFirstDefault == NULL) {
+- // No way to report errors from here.
+- return;
+- }
+- newFirstDefault->init(localeNameBuf, FALSE);
+- umtx_lock(NULL);
+- if (gDefaultLocale == NULL) {
+- gDefaultLocale = newFirstDefault; // Assignment to gDefaultLocale must happen inside mutex
+- newFirstDefault = NULL;
+- ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
+- }
+- // Else some other thread raced us through here, and set the new Locale.
+- // Use the hash table next.
+- umtx_unlock(NULL);
+- if (newFirstDefault == NULL) {
+- // We were successful in setting the locale, and we were the first one to set it.
+- return;
+- }
+- // else start using the hash table.
+- }
+-
+- // Lazy creation of the hash table itself, if needed.
+- UBool hashTableNeedsInit;
+- UMTX_CHECK(NULL, (gDefaultLocalesHashT == NULL), hashTableNeedsInit);
+- if (hashTableNeedsInit) {
+- status = U_ZERO_ERROR;
+- UHashtable *tHashTable = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
++ if (gDefaultLocalesHashT == NULL) {
++ gDefaultLocalesHashT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
+ if (U_FAILURE(status)) {
+- return;
+- }
+- uhash_setValueDeleter(tHashTable, deleteLocale);
+- umtx_lock(NULL);
+- if (gDefaultLocalesHashT == NULL) {
+- gDefaultLocalesHashT = tHashTable;
+- ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
+- } else {
+- uhash_close(tHashTable);
+- hashTableNeedsInit = FALSE;
++ return gDefaultLocale;
+ }
+- umtx_unlock(NULL);
++ uhash_setValueDeleter(gDefaultLocalesHashT, deleteLocale);
++ ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup);
+ }
+
+- // Hash table lookup, key is the locale full name
+- umtx_lock(NULL);
+ Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf);
+- if (newDefault != NULL) {
+- // We have the requested locale in the hash table already.
+- // Just set it as default. Inside the mutex lock, for those troublesome processors.
+- gDefaultLocale = newDefault;
+- umtx_unlock(NULL);
+- } else {
+- umtx_unlock(NULL);
+- // We haven't seen this locale id before.
+- // Create a new Locale object for it.
++ if (newDefault == NULL) {
+ newDefault = new Locale(Locale::eBOGUS);
+ if (newDefault == NULL) {
+- // No way to report errors from here.
+- return;
++ status = U_MEMORY_ALLOCATION_ERROR;
++ return gDefaultLocale;
+ }
+ newDefault->init(localeNameBuf, FALSE);
+-
+- // Add newly created Locale to the hash table of default Locales
+- const char *key = newDefault->getName();
+- U_ASSERT(uprv_strcmp(key, localeNameBuf) == 0);
+- umtx_lock(NULL);
+- Locale *hashTableVal = (Locale *)uhash_get(gDefaultLocalesHashT, key);
+- if (hashTableVal == NULL) {
+- if (hashTableNeedsInit) {
+- // This is the second request to set the locale.
+- // Cache the first one.
+- uhash_put(gDefaultLocalesHashT, (void *)gDefaultLocale->getName(), gDefaultLocale, &status);
+- }
+- uhash_put(gDefaultLocalesHashT, (void *)key, newDefault, &status);
+- gDefaultLocale = newDefault;
+- // ignore errors from hash table insert. (Couldn't do anything anyway)
+- // We can still set the default Locale,
+- // it just wont be cached, and will eventually leak.
+- } else {
+- // Some other thread raced us through here, and got the new Locale
+- // into the hash table before us. Use that one.
+- gDefaultLocale = hashTableVal; // Assignment to gDefaultLocale must happen inside mutex
+- delete newDefault;
++ uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status);
++ if (U_FAILURE(status)) {
++ return gDefaultLocale;
+ }
+- umtx_unlock(NULL);
+ }
++ gDefaultLocale = newDefault;
++ return gDefaultLocale;
+ }
++
+ U_NAMESPACE_END
+
+ /* sfb 07/21/99 */
+@@ -247,7 +184,8 @@
+ locale_set_default(const char *id)
+ {
+ U_NAMESPACE_USE
+- locale_set_default_internal(id);
++ UErrorCode status = U_ZERO_ERROR;
++ locale_set_default_internal(id, status);
+ }
+ /* end */
+
+@@ -255,7 +193,6 @@
+ locale_get_default(void)
+ {
+ U_NAMESPACE_USE
+-
+ return Locale::getDefault().getName();
+ }
+
+@@ -661,19 +598,14 @@
+ const Locale& U_EXPORT2
+ Locale::getDefault()
+ {
+- const Locale *retLocale;
+- UMTX_CHECK(NULL, gDefaultLocale, retLocale);
+- if (retLocale == NULL) {
+- locale_set_default_internal(NULL);
+- umtx_lock(NULL);
+- // Need a mutex in case some other thread set a new
+- // default inbetween when we set and when we get the new default. For
+- // processors with weak memory coherency, we might not otherwise see all
+- // of the newly created new default locale.
+- retLocale = gDefaultLocale;
+- umtx_unlock(NULL);
++ {
++ Mutex lock(&gDefaultLocaleMutex);
++ if (gDefaultLocale != NULL) {
++ return *gDefaultLocale;
++ }
+ }
+- return *retLocale;
++ UErrorCode status = U_ZERO_ERROR;
++ return *locale_set_default_internal(NULL, status);
+ }
+
+
+@@ -690,7 +622,7 @@
+ * This is a convenient way to access the default locale caching mechanisms.
+ */
+ const char *localeID = newLocale.getName();
+- locale_set_default_internal(localeID);
++ locale_set_default_internal(localeID, status);
+ }
+
+ Locale U_EXPORT2
+Index: icu-4.8.1.1/source/common/unicode/locid.h
+===================================================================
+--- icu-4.8.1.1.orig/source/common/unicode/locid.h 2013-03-21 11:21:45.053153118 -0400
++++ icu-4.8.1.1/source/common/unicode/locid.h 2013-03-21 11:21:45.041153115 -0400
+@@ -732,7 +732,7 @@
+ * A friend to allow the default locale to be set by either the C or C++ API.
+ * @internal
+ */
+- friend void locale_set_default_internal(const char *);
++ friend Locale *locale_set_default_internal(const char *, UErrorCode& status);
+ };
+
+ inline UBool
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 00000000000..cfb0c3d70d8
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,68 @@
+# Contributor: ant32 <antreimer@gmail.com>
+# Contributor: Rustam Tsurik <rustam.tsurik@gmail.com>
+pkgname=icu48
+_pkgname=icu
+pkgver=4.8.1.1
+pkgrel=3
+pkgdesc="International Components for Unicode library, version 4.8"
+arch=(i686 x86_64)
+url="http://www.icu-project.org/"
+license=('custom:"icu"')
+depends=('gcc-libs>=4.7.1-5' 'sh')
+
+source=("http://download.icu-project.org/files/${_pkgname}4c/${pkgver}/${_pkgname}4c-${pkgver//./_}-src.tgz"
+ "malayalam-rendering.patch"
+ "CVE-2011-4599.patch"
+ "indic-ccmp.patch"
+ "mlym-crash.patch"
+ "CVE-2013-0900.patch"
+ "fix-test.diff")
+
+md5sums=('ea93970a0275be6b42f56953cd332c17'
+ '9581cfaccbf93b6d6f7f7644bebcdafa'
+ '835c9e3ae0b76aa88a6ce144a42a3bce'
+ '6602e6d9727376174cbb1b688e5e3325'
+ 'a6a9daa1e3655c5058148af8903a443b'
+ '9528996e1e2099bb79d25fbd799a511e'
+ '766a677946f50029e0c01f5b8d30afec')
+
+prepare() {
+ cd ${srcdir}/icu/source
+
+ # apply security patches + fixes for Malayalan encoding
+ # patches taken from the Debian package,
+ # http://ftp.us.debian.org/debian/pool/main/i/icu/icu_4.8.1.1-12.debian.tar.gz
+
+ patch -p2 -i ../../malayalam-rendering.patch
+ patch -p2 -i ../../CVE-2011-4599.patch
+ patch -p2 -i ../../indic-ccmp.patch
+ patch -p2 -i ../../mlym-crash.patch
+ patch -p2 -i ../../CVE-2013-0900.patch
+ patch -p2 -i ../../fix-test.diff
+}
+
+build() {
+ cd ${srcdir}/icu/source
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man
+ # getting build failures -j1 '/bin/sh: ./../../bin/uconv: Text file busy'
+ make -j1
+}
+
+check() {
+ cd "$srcdir/icu/source"
+ make -k check # passes all
+}
+
+package() {
+ cd "${srcdir}/icu/source"
+
+ # Copy only .so libs to the destination dir
+ mkdir -p "${pkgdir}/usr/lib"
+ cp -a lib/libicu*48* "${pkgdir}/usr/lib"
+
+ # Install the license
+ install -Dm644 ${srcdir}/icu/license.html ${pkgdir}/usr/share/licenses/icu48/license.html
+}
diff --git a/fix-test.diff b/fix-test.diff
new file mode 100644
index 00000000000..738b81aa83a
--- /dev/null
+++ b/fix-test.diff
@@ -0,0 +1,11 @@
+--- icu.orig/source/test/intltest/dtfmttst.cpp 2013-10-04 22:48:00.000000000 +0200
++++ icu/source/test/intltest/dtfmttst.cpp 2014-06-13 19:34:40.611299572 +0200
+@@ -1129,7 +1129,7 @@
+ return;
+ }
+ parse2DigitYear(fmt, "5/6/17", date(117, UCAL_JUNE, 5));
+- parse2DigitYear(fmt, "4/6/34", date(34, UCAL_JUNE, 4));
++ parse2DigitYear(fmt, "4/6/34", date(134, UCAL_JUNE, 4));
+ }
+
+ // -------------------------------------
diff --git a/indic-ccmp.patch b/indic-ccmp.patch
new file mode 100644
index 00000000000..5c4c4383890
--- /dev/null
+++ b/indic-ccmp.patch
@@ -0,0 +1,50 @@
+Description: support CCMP for Indic
+Author: Harshula <harshula@debian.org>
+Bug: http://bugs.icu-project.org/trac/ticket/7601
+Bug-Debian: http://bugs.debian.org/655101
+
+Index: icu-4.8.1.1/source/layout/IndicReordering.cpp
+===================================================================
+--- icu-4.8.1.1.orig/source/layout/IndicReordering.cpp 2012-03-11 18:26:58.363626115 -0400
++++ icu-4.8.1.1/source/layout/IndicReordering.cpp 2012-03-11 18:27:30.375625255 -0400
+@@ -13,6 +13,7 @@
+
+ U_NAMESPACE_BEGIN
+
++#define ccmpFeatureTag LE_CCMP_FEATURE_TAG
+ #define loclFeatureTag LE_LOCL_FEATURE_TAG
+ #define initFeatureTag LE_INIT_FEATURE_TAG
+ #define nuktFeatureTag LE_NUKT_FEATURE_TAG
+@@ -35,6 +36,7 @@
+ #define caltFeatureTag LE_CALT_FEATURE_TAG
+ #define kernFeatureTag LE_KERN_FEATURE_TAG
+
++#define ccmpFeatureMask 0x00000001UL
+ #define loclFeatureMask 0x80000000UL
+ #define rphfFeatureMask 0x40000000UL
+ #define blwfFeatureMask 0x20000000UL
+@@ -73,7 +75,7 @@
+
+ #define repositionedGlyphMask 0x00000002UL
+
+-#define basicShapingFormsMask ( loclFeatureMask | nuktFeatureMask | akhnFeatureMask | rkrfFeatureMask | blwfFeatureMask | halfFeatureMask | vatuFeatureMask | cjctFeatureMask )
++#define basicShapingFormsMask ( ccmpFeatureMask | loclFeatureMask | nuktFeatureMask | akhnFeatureMask | rkrfFeatureMask | blwfFeatureMask | halfFeatureMask | vatuFeatureMask | cjctFeatureMask )
+ #define positioningFormsMask ( kernFeatureMask | distFeatureMask | abvmFeatureMask | blwmFeatureMask )
+ #define presentationFormsMask ( presFeatureMask | abvsFeatureMask | blwsFeatureMask | pstsFeatureMask | halnFeatureMask | caltFeatureMask )
+
+@@ -484,6 +486,7 @@
+ #define tagArray0 (rphfFeatureMask | tagArray1)
+
+ static const FeatureMap featureMap[] = {
++ {ccmpFeatureTag, ccmpFeatureMask},
+ {loclFeatureTag, loclFeatureMask},
+ {initFeatureTag, initFeatureMask},
+ {nuktFeatureTag, nuktFeatureMask},
+@@ -506,6 +509,7 @@
+ static const le_int32 featureCount = LE_ARRAY_SIZE(featureMap);
+
+ static const FeatureMap v2FeatureMap[] = {
++ {ccmpFeatureTag, ccmpFeatureMask},
+ {loclFeatureTag, loclFeatureMask},
+ {nuktFeatureTag, nuktFeatureMask},
+ {akhnFeatureTag, akhnFeatureMask},
diff --git a/malayalam-rendering.patch b/malayalam-rendering.patch
new file mode 100644
index 00000000000..97c2ad73c49
--- /dev/null
+++ b/malayalam-rendering.patch
@@ -0,0 +1,166 @@
+Description: revert change that broke Malayam rendering
+Origin: reverse patch from http://bugs.icu-project.org/trac/changeset/26090/icu/trunk/source/layout/IndicReordering.cpp
+Bug: http://bugs.icu-project.org/trac/ticket/8198
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=654200
+Bug-Debian: http://bugs.debian.org/591615
+
+Index: icu-4.8.1.1/source/layout/IndicReordering.cpp
+===================================================================
+--- icu-4.8.1.1.orig/source/layout/IndicReordering.cpp 2011-11-09 09:56:31.211396717 -0500
++++ icu-4.8.1.1/source/layout/IndicReordering.cpp 2011-11-09 09:56:44.739396527 -0500
+@@ -129,10 +129,6 @@
+ le_int32 fSMIndex;
+ FeatureMask fSMFeatures;
+
+- LEUnicode fPreBaseConsonant;
+- LEUnicode fPreBaseVirama;
+- le_int32 fPBCIndex;
+- FeatureMask fPBCFeatures;
+
+ void saveMatra(LEUnicode matra, le_int32 matraIndex, IndicClassTable::CharClass matraClass)
+ {
+@@ -179,8 +175,7 @@
+ fMpost(0), fMpostIndex(0), fLengthMark(0), fLengthMarkIndex(0), fAlLakuna(0), fAlLakunaIndex(0),
+ fMatraFeatures(0), fMPreOutIndex(-1), fMPreFixups(mpreFixups),
+ fVMabove(0), fVMpost(0), fVMIndex(0), fVMFeatures(0),
+- fSMabove(0), fSMbelow(0), fSMIndex(0), fSMFeatures(0),
+- fPreBaseConsonant(0), fPreBaseVirama(0), fPBCIndex(0), fPBCFeatures(0)
++ fSMabove(0), fSMbelow(0), fSMIndex(0), fSMFeatures(0)
+ {
+ // nothing else to do...
+ }
+@@ -199,8 +194,6 @@
+
+ fVMabove = fVMpost = 0;
+ fSMabove = fSMbelow = 0;
+-
+- fPreBaseConsonant = fPreBaseVirama = 0;
+ }
+
+ void writeChar(LEUnicode ch, le_uint32 charIndex, FeatureMask charFeatures)
+@@ -396,14 +389,6 @@
+ }
+ }
+
+- void notePreBaseConsonant(le_uint32 index,LEUnicode PBConsonant, LEUnicode PBVirama, FeatureMask features)
+- {
+- fPBCIndex = index;
+- fPreBaseConsonant = PBConsonant;
+- fPreBaseVirama = PBVirama;
+- fPBCFeatures = features;
+- }
+-
+ void noteBaseConsonant()
+ {
+ if (fMPreFixups != NULL && fMPreOutIndex >= 0) {
+@@ -483,22 +468,6 @@
+ }
+ }
+
+- void writePreBaseConsonant()
+- {
+- // The TDIL spec says that consonant + virama + RRA should produce a rakar in Malayalam. However,
+- // it seems that almost none of the fonts for Malayalam are set up to handle this.
+- // So, we're going to force the issue here by using the rakar as defined with RA in most fonts.
+-
+- if (fPreBaseConsonant == 0x0d31) { // RRA
+- fPreBaseConsonant = 0x0d30; // RA
+- }
+-
+- if (fPreBaseConsonant != 0) {
+- writeChar(fPreBaseConsonant, fPBCIndex, fPBCFeatures);
+- writeChar(fPreBaseVirama,fPBCIndex-1,fPBCFeatures);
+- }
+- }
+-
+ le_int32 getOutputIndex()
+ {
+ return fOutIndex;
+@@ -765,7 +734,6 @@
+ lastConsonant -= 1;
+ }
+
+-
+ IndicClassTable::CharClass charClass = CC_RESERVED;
+ IndicClassTable::CharClass nextClass = CC_RESERVED;
+ le_int32 baseConsonant = lastConsonant;
+@@ -773,11 +741,9 @@
+ le_int32 postBaseLimit = classTable->scriptFlags & SF_POST_BASE_LIMIT_MASK;
+ le_bool seenVattu = FALSE;
+ le_bool seenBelowBaseForm = FALSE;
+- le_bool seenPreBaseForm = FALSE;
+ le_bool hasNukta = FALSE;
+ le_bool hasBelowBaseForm = FALSE;
+ le_bool hasPostBaseForm = FALSE;
+- le_bool hasPreBaseForm = FALSE;
+
+ if (postBase < markStart && classTable->isNukta(chars[postBase])) {
+ charClass = CC_NUKTA;
+@@ -791,22 +757,14 @@
+
+ hasBelowBaseForm = IndicClassTable::hasBelowBaseForm(charClass) && !hasNukta;
+ hasPostBaseForm = IndicClassTable::hasPostBaseForm(charClass) && !hasNukta;
+- hasPreBaseForm = IndicClassTable::hasPreBaseForm(charClass) && !hasNukta;
+
+ if (IndicClassTable::isConsonant(charClass)) {
+ if (postBaseLimit == 0 || seenVattu ||
+ (baseConsonant > baseLimit && !classTable->isVirama(chars[baseConsonant - 1])) ||
+- !(hasBelowBaseForm || hasPostBaseForm || hasPreBaseForm)) {
++ !(hasBelowBaseForm || hasPostBaseForm)) {
+ break;
+ }
+
+- // Note any pre-base consonants
+- if ( baseConsonant == lastConsonant && lastConsonant > 0 &&
+- hasPreBaseForm && classTable->isVirama(chars[baseConsonant - 1])) {
+- output.notePreBaseConsonant(lastConsonant,chars[lastConsonant],chars[lastConsonant-1],tagArray2);
+- seenPreBaseForm = TRUE;
+-
+- }
+ // consonants with nuktas are never vattus
+ seenVattu = IndicClassTable::isVattu(charClass) && !hasNukta;
+
+@@ -839,14 +797,12 @@
+ }
+
+ // write any pre-base consonants
+- output.writePreBaseConsonant();
+-
+ le_bool supressVattu = TRUE;
+
+ for (i = baseLimit; i < baseConsonant; i += 1) {
+ LEUnicode ch = chars[i];
+- // Don't put 'pstf' or 'blwf' on anything before the base consonant.
+- FeatureMask features = tagArray1 & ~( pstfFeatureMask | blwfFeatureMask );
++ // Don't put 'blwf' on first consonant.
++ FeatureMask features = (i == baseLimit? tagArray2 : tagArray1);
+
+ charClass = classTable->getCharClass(ch);
+ nextClass = classTable->getCharClass(chars[i + 1]);
+@@ -897,7 +853,7 @@
+ }
+
+ // write below-base consonants
+- if (baseConsonant != lastConsonant && !seenPreBaseForm) {
++ if (baseConsonant != lastConsonant) {
+ for (i = bcSpan + 1; i < postBase; i += 1) {
+ output.writeChar(chars[i], i, tagArray1);
+ }
+@@ -927,7 +883,7 @@
+
+ // write post-base consonants
+ // FIXME: does this put the right tags on post-base consonants?
+- if (baseConsonant != lastConsonant && !seenPreBaseForm) {
++ if (baseConsonant != lastConsonant) {
+ if (postBase <= lastConsonant) {
+ for (i = postBase; i <= lastConsonant; i += 1) {
+ output.writeChar(chars[i], i, tagArray3);
+@@ -1195,7 +1151,7 @@
+ }
+
+
+-void IndicReordering::getDynamicProperties( DynamicProperties *, const IndicClassTable *classTable ) {
++void IndicReordering::getDynamicProperties( DynamicProperties */*dProps*/, const IndicClassTable *classTable ) {
+
+
+ LEUnicode currentChar;
diff --git a/mlym-crash.patch b/mlym-crash.patch
new file mode 100644
index 00000000000..44f169f3189
--- /dev/null
+++ b/mlym-crash.patch
@@ -0,0 +1,19 @@
+Description: Fix crash on rendering incremental Malayalam text input
+Author: Caolán McNamara <caolanm@redhat.com>
+Origin: other, https://ssl.icu-project.org/trac/ticket/9948
+Forwarded: https://ssl.icu-project.org/trac/ticket/9948
+Last-Update: 2013-03-13
+
+Index: b/source/layout/IndicClassTables.cpp
+===================================================================
+--- a/source/layout/IndicClassTables.cpp
++++ b/source/layout/IndicClassTables.cpp
+@@ -273,7 +273,7 @@
+
+ static const IndicClassTable kndaClassTable = {0x0C80, 0x0CEF, 4, KNDA_SCRIPT_FLAGS, kndaCharClasses, kndaSplitTable};
+
+-static const IndicClassTable mlymClassTable = {0x0D00, 0x0D6F, 3, MLYM_SCRIPT_FLAGS, mlymCharClasses, mlymSplitTable};
++static const IndicClassTable mlymClassTable = {0x0D00, 0x0D6F, 4, MLYM_SCRIPT_FLAGS, mlymCharClasses, mlymSplitTable};
+
+ static const IndicClassTable sinhClassTable = {0x0D80, 0x0DF4, 4, SINH_SCRIPT_FLAGS, sinhCharClasses, sinhSplitTable};
+