From d09860faff8dac4c63db6e22eeb556a15c2ffaeb Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 21 Mar 2013 16:20:15 -0500 Subject: [PATCH] Add unpaged memory mode to TQString and TQLineEdit Fix designer build warnings --- src/tools/qstring.cpp | 79 ++++++++++++++++++- src/tools/qstring.h | 14 +++- src/widgets/qlineedit.cpp | 46 +++++++++-- src/widgets/qlineedit.h | 2 +- tools/designer/designer/designerappiface.cpp | 4 + tools/designer/designer/designerappiface.h | 1 + tools/designer/interfaces/designerinterface.h | 21 +++++ 7 files changed, 153 insertions(+), 14 deletions(-) diff --git a/src/tools/qstring.cpp b/src/tools/qstring.cpp index 24b8164..8717f6a 100644 --- a/src/tools/qstring.cpp +++ b/src/tools/qstring.cpp @@ -65,10 +65,18 @@ #if defined(Q_WS_WIN) #include "qt_windows.h" #endif +#if defined(Q_OS_LINUX) +#include +#endif #if !defined( QT_NO_COMPONENT ) && !defined( QT_LITE_COMPONENT ) #include "qcleanuphandler.h" #endif +#if defined(Q_OS_LINUX) +#define LINUX_MEMLOCK_LIMIT_BYTES 16384 +#define LINUX_MEMLOCK_LIMIT_CHARACTERS LINUX_MEMLOCK_LIMIT_BYTES/sizeof(QChar) +#endif + #ifndef LLONG_MAX #define LLONG_MAX Q_INT64_C(9223372036854775807) #endif @@ -1025,6 +1033,14 @@ static inline bool format(QChar::Decomposition tag, QString & str, } // format() #endif +QStringData::~QStringData() { + if ( unicode ) delete[] ((char*)unicode); + if ( ascii && security_unpaged ) { + munlock(ascii, LINUX_MEMLOCK_LIMIT_BYTES); + } + if ( ascii ) delete[] ascii; +} + /* QString::compose() and visual() were developed by Gordon Tisher , with input from Lars Knoll , @@ -1202,6 +1218,15 @@ static QChar* internalLatin1ToUnicode( const char *str, uint* len, return result; } +/*! + ABI compatibility +*/ + +char* QString::unicodeToLatin1(const QChar *uc, uint l) +{ + return unicodeToLatin1(uc, l, false); +} + /*! This utility function converts \a l 16-bit characters from \a uc to ASCII, returning a '\0'-terminated string. @@ -1209,13 +1234,19 @@ static QChar* internalLatin1ToUnicode( const char *str, uint* len, The caller is responsible for deleting the resultant string with delete[]. */ -char* QString::unicodeToLatin1(const QChar *uc, uint l) + +char* QString::unicodeToLatin1(const QChar *uc, uint l, bool unpaged) { if (!uc) { return 0; } char *a = new char[l+1]; char *result = a; + if (unpaged) { +#if defined(Q_OS_LINUX) + mlock(result, LINUX_MEMLOCK_LIMIT_BYTES); +#endif + } while (l--) { *a++ = (uc->unicode() > 0xff) ? '?' : (char)uc->unicode(); uc++; @@ -1707,8 +1738,10 @@ void QString::setLength( uint newLen ) if ( nd ) { uint len = QMIN( d->len, newLen ); memcpy( nd, d->unicode, sizeof(QChar) * len ); + bool unpaged = d->security_unpaged; deref(); d = new QStringData( nd, newLen, newMax ); + setSecurityUnPaged(unpaged); } } else { d->len = newLen; @@ -1760,8 +1793,10 @@ void QString::reserve( uint minCapacity ) uint len = d->len; if ( len ) memcpy( nd, d->unicode, sizeof(QChar) * len ); + bool unpaged = d->security_unpaged; deref(); d = new QStringData( nd, len, minCapacity ); + setSecurityUnPaged(unpaged); } } } @@ -1780,8 +1815,10 @@ void QString::squeeze() uint len = d->len; if ( len ) memcpy( nd, d->unicode, sizeof(QChar) * len ); + bool unpaged = d->security_unpaged; deref(); d = new QStringData( nd, len, len ); + setSecurityUnPaged(unpaged); } } } @@ -2744,9 +2781,11 @@ QString& QString::fill( QChar c, int len ) if ( len == 0 ) { *this = ""; } else { + bool unpaged = d->security_unpaged; deref(); QChar * nd = QT_ALLOC_QCHAR_VEC( len ); d = new QStringData(nd,len,len); + setSecurityUnPaged(unpaged); while (len--) *nd++ = c; } return *this; @@ -5678,8 +5717,15 @@ QString &QString::operator+=( char c ) const char* QString::latin1() const { if ( !d->ascii || !d->islatin1 ) { + if (d->security_unpaged) { +#if defined(Q_OS_LINUX) + if (d->ascii) { + munlock(d->ascii, LINUX_MEMLOCK_LIMIT_BYTES); + } +#endif + } delete [] d->ascii; - d->ascii = unicodeToLatin1( d->unicode, d->len ); + d->ascii = unicodeToLatin1( d->unicode, d->len, d->security_unpaged ); d->islatin1 = TRUE; } return d->ascii; @@ -5699,10 +5745,22 @@ const char* QString::ascii() const #ifndef QT_NO_TEXTCODEC if ( QTextCodec::codecForCStrings() ) { if ( !d->ascii || d->islatin1 ) { + if (d->security_unpaged) { +#if defined(Q_OS_LINUX) + if (d->ascii) { + munlock(d->ascii, LINUX_MEMLOCK_LIMIT_BYTES); + } +#endif + } delete [] d->ascii; if (d->unicode) { QCString s = QTextCodec::codecForCStrings()->fromUnicode( *this ); d->ascii = new char[s.length() + 1]; + if (d->security_unpaged) { +#if defined(Q_OS_LINUX) + mlock(d->ascii, LINUX_MEMLOCK_LIMIT_BYTES); +#endif + } memcpy(d->ascii, s.data(), s.length() + 1); } else { d->ascii = 0; @@ -5715,6 +5773,23 @@ const char* QString::ascii() const return latin1(); } +void QString::setSecurityUnPaged(bool lock) { + if (lock != d->security_unpaged) { + if (d->security_unpaged) { + if (d->ascii) { + munlock(d->ascii, LINUX_MEMLOCK_LIMIT_BYTES); + } + d->security_unpaged = false; + } + else { + if (d->ascii) { + mlock(d->ascii, LINUX_MEMLOCK_LIMIT_BYTES); + } + d->security_unpaged = true; + } + } +} + /*! Returns the string encoded in UTF-8 format. diff --git a/src/tools/qstring.h b/src/tools/qstring.h index 587d0f2..58830db 100644 --- a/src/tools/qstring.h +++ b/src/tools/qstring.h @@ -360,11 +360,10 @@ inline bool operator>( QChar c1, QChar c2 ) { return !(c2>=c1); } // internal struct Q_EXPORT QStringData : public QShared { QStringData() : - QShared(), unicode(0), ascii(0), len(0), issimpletext(TRUE), maxl(0), islatin1(FALSE) { ref(); } + QShared(), unicode(0), ascii(0), len(0), issimpletext(TRUE), maxl(0), islatin1(FALSE), security_unpaged(FALSE) { ref(); } QStringData(QChar *u, uint l, uint m) : - QShared(), unicode(u), ascii(0), len(l), issimpletext(FALSE), maxl(m), islatin1(FALSE) { } - ~QStringData() { if ( unicode ) delete[] ((char*)unicode); - if ( ascii ) delete[] ascii; } + QShared(), unicode(u), ascii(0), len(l), issimpletext(FALSE), maxl(m), islatin1(FALSE), security_unpaged(FALSE) { } + ~QStringData(); void deleteSelf(); QChar *unicode; @@ -389,6 +388,8 @@ struct Q_EXPORT QStringData : public QShared { #endif uint islatin1 : 1; + bool security_unpaged : 1; + private: #if defined(Q_DISABLE_COPY) QStringData( const QStringData& ); @@ -750,7 +751,12 @@ private: // needed for QDeepCopy void detach(); + + void setSecurityUnPaged(bool lock); + static char* unicodeToLatin1( const QChar*, uint len, bool unpaged ); + friend class QDeepCopy; + friend class QLineEdit; }; class Q_EXPORT QCharRef { diff --git a/src/widgets/qlineedit.cpp b/src/widgets/qlineedit.cpp index d786829..2a71656 100644 --- a/src/widgets/qlineedit.cpp +++ b/src/widgets/qlineedit.cpp @@ -63,6 +63,9 @@ #include "../kernel/qinternal_p.h" #include "private/qtextlayout_p.h" #include "qvaluevector.h" +#if defined(Q_OS_LINUX) +#include +#endif #if defined(QT_ACCESSIBILITY_SUPPORT) #include "qaccessible.h" #endif @@ -74,6 +77,11 @@ #define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k) #endif +#if defined(Q_OS_LINUX) +#define LINUX_MEMLOCK_LIMIT_BYTES 16384 +#define LINUX_MEMLOCK_LIMIT_CHARACTERS LINUX_MEMLOCK_LIMIT_BYTES/sizeof(QChar) +#endif + #define innerMargin 1 struct QLineEditPrivate : public Qt @@ -451,6 +459,10 @@ QLineEdit::QLineEdit( const QString& contents, const QString &inputMask, QWidget QLineEdit::~QLineEdit() { + if ((d->echoMode == NoEcho) || (d->echoMode == Password) || (d->echoMode == PasswordThreeStars)) { + d->text.fill(QChar(0)); + munlock(d->text.d->unicode, LINUX_MEMLOCK_LIMIT_BYTES); + } delete [] d->maskData; delete d; } @@ -500,11 +512,16 @@ void QLineEdit::setText( const QString& text) QString QLineEdit::displayText() const { - if ( d->echoMode == NoEcho ) + if ( d->echoMode == NoEcho ) { return QString::fromLatin1(""); + } QString res = d->text; - if ( d->echoMode == Password ) + if ( d->echoMode == Password ) { res.fill( passwordChar() ); + } + else if ( d->echoMode == PasswordThreeStars ) { + res.fill( passwordChar(), res.length()*3 ); + } return ( res.isNull() ? QString::fromLatin1("") : res ); } @@ -598,11 +615,26 @@ QLineEdit::EchoMode QLineEdit::echoMode() const void QLineEdit::setEchoMode( EchoMode mode ) { - if (mode == (EchoMode)d->echoMode) + if (mode == (EchoMode)d->echoMode) { return; + } +#if defined(Q_OS_LINUX) + if (((mode == NoEcho) || (mode == Password) || (mode == PasswordThreeStars)) && ((EchoMode)d->echoMode == Normal)) { + if ((uint)d->maxLength > (LINUX_MEMLOCK_LIMIT_CHARACTERS-1)) { + d->maxLength = LINUX_MEMLOCK_LIMIT_CHARACTERS-1; + } + d->text.reserve(LINUX_MEMLOCK_LIMIT_CHARACTERS); + mlock(d->text.d->unicode, LINUX_MEMLOCK_LIMIT_BYTES); + d->text.setSecurityUnPaged(true); + } + else { + d->text.setSecurityUnPaged(false); + munlock(d->text.d->unicode, LINUX_MEMLOCK_LIMIT_BYTES); + } +#endif d->echoMode = mode; d->updateTextLayout(); - setInputMethodEnabled( mode == Normal ); + setInputMethodEnabled( ( mode == Normal ) || ( mode == Password) ); update(); } @@ -1688,12 +1720,12 @@ void QLineEdit::keyPressEvent( QKeyEvent * e ) case Key_Right: case Key_Left: if ( d->isRightToLeft() == (e->key() == Key_Right) ) { - if ( echoMode() == Normal ) + if (( echoMode() == Normal ) || ( echoMode() == Password )) cursorWordBackward( e->state() & ShiftButton ); else home( e->state() & ShiftButton ); } else { - if ( echoMode() == Normal ) + if (( echoMode() == Normal ) || ( echoMode() == Password )) cursorWordForward( e->state() & ShiftButton ); else end( e->state() & ShiftButton ); @@ -2069,7 +2101,7 @@ void QLineEdit::drawContents( QPainter *p ) // Asian users regard IM selection text as cursor on candidate // selection phase of input method, so ordinary cursor should be // invisible if IM selection text exists. - if ( d->cursorVisible && !supressCursor && !d->hasIMSelection() ) { + if ( d->cursorVisible && !supressCursor && !d->hasIMSelection() && (d->echoMode != PasswordThreeStars) ) { QPoint from( topLeft.x() + cix, lineRect.top() ); QPoint to = from + QPoint( 0, lineRect.height() ); p->drawLine( from, to ); diff --git a/src/widgets/qlineedit.h b/src/widgets/qlineedit.h index 3778e2a..b7e0fb8 100644 --- a/src/widgets/qlineedit.h +++ b/src/widgets/qlineedit.h @@ -94,7 +94,7 @@ public: bool frame() const; - enum EchoMode { Normal, NoEcho, Password }; + enum EchoMode { Normal, NoEcho, Password, PasswordThreeStars }; EchoMode echoMode() const; bool isReadOnly() const; diff --git a/tools/designer/designer/designerappiface.cpp b/tools/designer/designer/designerappiface.cpp index 770d39d..722d33f 100644 --- a/tools/designer/designer/designerappiface.cpp +++ b/tools/designer/designer/designerappiface.cpp @@ -58,6 +58,10 @@ DesignerInterfaceImpl::DesignerInterfaceImpl( MainWindow *mw ) { } +DesignerInterfaceImpl::~DesignerInterfaceImpl() +{ +} + QRESULT DesignerInterfaceImpl::queryInterface( const QUuid &uuid, QUnknownInterface** iface ) { *iface = 0; diff --git a/tools/designer/designer/designerappiface.h b/tools/designer/designer/designerappiface.h index 91c29a5..24548f2 100644 --- a/tools/designer/designer/designerappiface.h +++ b/tools/designer/designer/designerappiface.h @@ -47,6 +47,7 @@ class DesignerInterfaceImpl : public DesignerInterface { public: DesignerInterfaceImpl( MainWindow *mw ); + virtual ~DesignerInterfaceImpl(); DesignerProject *currentProject() const; DesignerFormWindow *currentForm() const; diff --git a/tools/designer/interfaces/designerinterface.h b/tools/designer/interfaces/designerinterface.h index 8988da0..8c89941 100644 --- a/tools/designer/interfaces/designerinterface.h +++ b/tools/designer/interfaces/designerinterface.h @@ -108,6 +108,9 @@ struct DesignerInterface : public QUnknownInterface struct DesignerProject { + DesignerProject() {} + virtual ~DesignerProject() {} + virtual QPtrList formList() const = 0; virtual QStringList formNames() const = 0; virtual QString formFileName( const QString &form ) const = 0; @@ -149,6 +152,9 @@ struct DesignerProject struct DesignerDatabase { + DesignerDatabase() {} + virtual ~DesignerDatabase() {} + virtual QString name() const = 0; virtual void setName( const QString & ) = 0; virtual QString driver() const = 0; @@ -173,12 +179,18 @@ struct DesignerDatabase struct DesignerPixmapCollection { + DesignerPixmapCollection() {} + virtual ~DesignerPixmapCollection() {} + virtual void addPixmap( const QPixmap &p, const QString &name, bool force ) = 0; virtual QPixmap pixmap( const QString &name ) const = 0; }; struct DesignerFormWindow { + DesignerFormWindow() {} + virtual ~DesignerFormWindow() {} + virtual QString name() const = 0; virtual void setName( const QString &n ) = 0; virtual QString fileName() const = 0; @@ -248,16 +260,25 @@ struct DesignerFormWindow struct DesignerSourceFile { + DesignerSourceFile() {} + virtual ~DesignerSourceFile() {} + virtual QString fileName() const = 0; }; struct DesignerDock { + DesignerDock() {} + virtual ~DesignerDock() {} + virtual QDockWindow *dockWindow() const = 0; }; struct DesignerOutputDock { + DesignerOutputDock() {} + virtual ~DesignerOutputDock() {} + virtual QWidget *addView( const QString &pageName ) = 0; virtual void appendDebug( const QString & ) = 0; virtual void clearDebug() = 0;