Author: wyoung
Date: Sat Jul  7 00:44:43 2007
New Revision: 1651

URL: http://svn.gna.org/viewcvs/mysqlpp?rev=1651&view=rev
Log:
Reverted previous examples/cgi_jpeg.cpp change.  It just covered up
further embedded null handling problems in the library.  Fixed these
by removing every last use of c_str() in lib/manip.cpp, using C++
string length information wherever possible in there, and changed
const_string class to make copies of its data.

The latter is critical: when using SSQLS with BLOBs, the data gets
copied as ColData_Tmpl<const_string>, which used to just keep a
copy of the string pointer.  This didn't work out right with SSQLS,
because the pointed-to buffer went away after SSQLS population, so
the program could crash on trying to use the BLOB field.  (It didn't
always, which is why 2.3.0 got released with this bug.  Trying the
feature with a bigger BLOB tickled the bug.)

Modified:
    trunk/examples/cgi_jpeg.cpp
    trunk/lib/const_string.h
    trunk/lib/manip.cpp

Modified: trunk/examples/cgi_jpeg.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/cgi_jpeg.cpp?rev=1651&r1=1650&r2=1651&view=diff
==============================================================================
--- trunk/examples/cgi_jpeg.cpp (original)
+++ trunk/examples/cgi_jpeg.cpp Sat Jul  7 00:44:43 2007
@@ -83,10 +83,9 @@
                ResUse res = query.use();
                if (res) {
                        images img = res.fetch_row();
-                       string img_data(img.data, img.data.length());
                        cout << "Content-type: image/jpeg" << endl;
-                       cout << "Content-length: " << img_data.length() << 
"\n\n";
-                       cout << img_data;
+                       cout << "Content-length: " << img.data.length() << 
"\n\n";
+                       cout << img.data;
                }
                else {
                        cout << "Content-type: text/plain" << endl << endl;

Modified: trunk/lib/const_string.h
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/const_string.h?rev=1651&r1=1650&r2=1651&view=diff
==============================================================================
--- trunk/lib/const_string.h (original)
+++ trunk/lib/const_string.h Sat Jul  7 00:44:43 2007
@@ -43,10 +43,9 @@
 ///
 /// This class implements a small subset of the standard string class.
 ///
-/// Objects are created from an existing <tt>const char*</tt> variable
-/// by copying the pointer only.  Therefore, the object pointed to by
-/// that pointer needs to exist for at least as long as the const_string
-/// object that wraps it.
+/// As of MySQL++ 2.3, it makes a copy of the string we are initialized
+/// with, instead of just copying the pointer.  This is required to
+/// avoid problems with the new SSQLS + BLOB support.
 class MYSQLPP_EXPORT const_string
 {
 public:
@@ -78,37 +77,61 @@
 
        /// \brief Create empty string
        const_string() :
-       str_data_(""),
+       str_data_(0),
        length_(0)
        {
        }
        
        /// \brief Initialize string from existing C++ string
        const_string(const std::string& str) :
-       str_data_(str.data()),
+       str_data_(0),
        length_(str.length())
        {
+               str_data_ = new char[length_];
+               memcpy(str_data_, str.data(), length_);
        }
        
        /// \brief Initialize string from existing C string
        const_string(const char* str) :
-       str_data_(str),
+       str_data_(0),
        length_(size_type(strlen(str)))
        {
+               str_data_ = new char[length_];
+               memcpy(str_data_, str, length_);
        }
        
        /// \brief Initialize string from existing C string of known length
        const_string(const char* str, size_type len) :
-       str_data_(str),
+       str_data_(0),
        length_(size_type(len))
        {
-       }
-       
-       /// \brief Assignment operator
+               str_data_ = new char[length_];
+               memcpy(str_data_, str, length_);
+       }
+
+       /// \brief Destroy string
+       ~const_string()
+       {
+               delete[] str_data_;
+       }
+       
+       /// \brief Assignment operator, from C string
        const_string& operator=(const char* str)
        {
-               str_data_ = str;
+               delete[] str_data_;
                length_ = size_type(strlen(str));
+               str_data_ = new char[length_];
+               memcpy(str_data_, str, length_);
+               return *this;
+       }
+
+       /// \brief Assignment operator, from other const_string
+       const_string& operator=(const const_string& cs)
+       {
+               delete[] str_data_;
+               length_ = cs.length_;
+               str_data_ = new char[length_];
+               memcpy(str_data_, cs.str_data_, length_);
                return *this;
        }
 
@@ -116,7 +139,7 @@
        size_type length() const { return length_; }
 
        /// \brief Return number of characters in string
-       size_type size() const { return length(); }
+       size_type size() const { return length_; }
 
        /// \brief Return iterator pointing to the first character of
        /// the string
@@ -173,7 +196,7 @@
        }
 
 private:
-       const char* str_data_;
+       char* str_data_;
        size_type length_;
 };
 

Modified: trunk/lib/manip.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/manip.cpp?rev=1651&r1=1650&r2=1651&view=diff
==============================================================================
--- trunk/lib/manip.cpp (original)
+++ trunk/lib/manip.cpp Sat Jul  7 00:44:43 2007
@@ -56,17 +56,18 @@
 SQLQueryParms& operator <<(quote_type2 p, SQLString& in)
 {
        if (in.is_string) {
-               SQLString in2;
+               SQLString in2('\'');
                if (in.dont_escape) {
-                       in2 = '\'' + in + '\'';
+                       in2 += in;
+                       in2 += '\'';
                        in2.processed = true;
                        return *p.qparms << in2;
                }
                else {
-                       char* s = new char[in.size() * 2 + 1];
-                       mysql_escape_string(s, in.c_str(),
-                                       static_cast<unsigned long>(in.size()));
-                       in2 = SQLString('\'') + s + '\'';
+                       char* s = new char[in.length() * 2 + 1];
+                       size_t len = mysql_escape_string(s, in.data(), 
in.length());
+                       in2.append(s, len);
+                       in2 += '\'';
                        in2.processed = true;
                        *p.qparms << in2;
                        delete[] s;
@@ -88,10 +89,13 @@
 template <>
 ostream& operator <<(quote_type1 o, const string& in)
 {
-       char* s = new char[in.size() * 2 + 1];
-       mysql_escape_string(s, in.c_str(),
-                       static_cast<unsigned long>(in.size()));
-       *o.ostr << '\'' << s << '\'';
+       char* s = new char[in.length() * 2 + 1];
+       size_t len = mysql_escape_string(s, in.data(), in.length());
+
+       o.ostr->write("'", 1);
+       o.ostr->write(s, len);
+       o.ostr->write("'", 1);
+
        delete[] s;
        return *o.ostr;
 }
@@ -105,10 +109,14 @@
 template <>
 ostream& operator <<(quote_type1 o, const char* const& in)
 {
-       size_t size = strlen(in);
-       char* s = new char[size * 2 + 1];
-       mysql_escape_string(s, in, static_cast<unsigned long>(size));
-       *o.ostr << '\'' << s << '\'';
+       size_t len = strlen(in);
+       char* s = new char[len * 2 + 1];
+       len = mysql_escape_string(s, in, len);
+
+       o.ostr->write("'", 1);
+       o.ostr->write(s, len);
+       o.ostr->write("'", 1);
+
        delete[] s;
        return *o.ostr;
 }
@@ -120,21 +128,21 @@
 inline ostream& _manip(quote_type1 o, const ColData_Tmpl<Str>& in)
 {
        if (in.escape_q()) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(),
-                               static_cast<unsigned long>(in.size()));
-               if (in.quote_q())
-                       *o.ostr << '\'' << s << '\'';
-               else
-                       *o.ostr << s;
-               delete[] s;
-       }
-       else if (in.quote_q()) {
-               *o.ostr << '\'' << in.c_str() << '\'';
-       }
-       else {
-               *o.ostr << in.c_str();
-       }
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+
+               if (in.quote_q()) o.ostr->write("'", 1);
+               o.ostr->write(s, len);
+               if (in.quote_q()) o.ostr->write("'", 1);
+
+               delete[] s;
+       }
+       else {
+               if (in.quote_q()) o.ostr->write("'", 1);
+               o.ostr->write(in.data(), in.length());
+               if (in.quote_q()) o.ostr->write("'", 1);
+       }
+
        return *o.ostr;
 }
 
@@ -175,27 +183,30 @@
 
 ostream& operator <<(ostream& o, const ColData_Tmpl<string>& in)
 {
-       if (dont_quote_auto || (o.rdbuf() == cout.rdbuf()) ||
-                       (o.rdbuf() == cerr.rdbuf())) {
-               return o << in.c_str();
-       }
-
-       if (in.escape_q()) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(),
-                               static_cast<unsigned long>(in.size()));
-               if (in.quote_q())
-                       o << '\'' << s << '\'';
-               else
-                       o << s;
-               delete[] s;
-       }
-       else if (in.quote_q()) {
-               o << '\'' << in.c_str() << '\'';
-       }
-       else {
-               o << in.c_str();
-       }
+       // Decide if we're allowed to escape or quote the data.
+       bool transform_ok =
+                       !dont_quote_auto &&
+                       (o.rdbuf() != cout.rdbuf()) &&
+                       (o.rdbuf() != cerr.rdbuf());
+
+       if (transform_ok && in.escape_q()) {
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+
+               if (in.quote_q()) o << '\'';
+               o.write(s, len);
+               if (in.quote_q()) o << '\'';
+
+               delete[] s;
+       }
+       else {
+               bool add_quote = transform_ok && in.quote_q();
+
+               if (add_quote) o << '\'';
+               o.write(in.data(), in.length());
+               if (add_quote) o << '\'';
+       }
+
        return o;
 }
 
@@ -209,28 +220,30 @@
 
 ostream& operator <<(ostream& o, const ColData_Tmpl<const_string>& in)
 {
-       if (dont_quote_auto || (o.rdbuf() == cout.rdbuf()) ||
-                       (o.rdbuf() == cerr.rdbuf())) {
-               // Write out the raw data.  Have to do it this way in case
-               // it's a BLOB field.
-               return o.write(in.data(), in.length());
-       }
-
-       if (in.escape_q()) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(), in.size());
-               if (in.quote_q())
-                       o << '\'' << s << '\'';
-               else
-                       o << s;
-               delete[] s;
-       }
-       else if (in.quote_q()) {
-               o << '\'' << in.c_str() << '\'';
-       }
-       else {
-               o << in.c_str();
-       }
+       // Decide if we're allowed to escape or quote the data.
+       bool transform_ok =
+                       !dont_quote_auto &&
+                       (o.rdbuf() != cout.rdbuf()) &&
+                       (o.rdbuf() != cerr.rdbuf());
+
+       if (transform_ok && in.escape_q()) {
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+
+               if (in.quote_q()) o << '\'';
+               o.write(s, len);
+               if (in.quote_q()) o << '\'';
+
+               delete[] s;
+       }
+       else {
+               bool add_quote = transform_ok && in.quote_q();
+
+               if (add_quote) o << '\'';
+               o.write(in.data(), in.length());
+               if (add_quote) o << '\'';
+       }
+
        return o;
 }
 
@@ -244,25 +257,24 @@
 Query& operator <<(Query& o, const ColData_Tmpl<string>& in)
 {
        if (dont_quote_auto) {
-               o << in.c_str();
-               return o;
-       }
-       if (in.escape_q()) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(),
-                               static_cast<unsigned long>(in.size()));
-               if (in.quote_q())
-                       static_cast<ostream&>(o) << '\'' << s << '\'';
-               else
-                       static_cast<ostream&>(o) << s;
-               delete[] s;
-       }
-       else if (in.quote_q()) {
-               static_cast<ostream&>(o) << '\'' << in.c_str() << '\'';
-       }
-       else {
-               static_cast<ostream&>(o) << in.c_str();
-       }
+               o.write(in.data(), in.length());
+       }
+       else if (in.escape_q()) {
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+
+               if (in.quote_q()) o.write("'", 1);
+               o.write(s, len);
+               if (in.quote_q()) o.write("'", 1);
+
+               delete[] s;
+       }
+       else {
+               if (in.quote_q()) o.write("'", 1);
+               o.write(in.data(), in.length());
+               if (in.quote_q()) o.write("'", 1);
+       }
+
        return o;
 }
 
@@ -276,24 +288,24 @@
 Query& operator <<(Query& o, const ColData_Tmpl<const_string>& in)
 {
        if (dont_quote_auto) {
-               o << in.c_str();
-               return o;
-       }
-       if (in.escape_q()) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(), in.size());
-               if (in.quote_q())
-                       static_cast<ostream&>(o) << '\'' << s << '\'';
-               else
-                       static_cast<ostream&>(o) << s;
-               delete[] s;
-       }
-       else if (in.quote_q()) {
-               static_cast<ostream&>(o) << '\'' << in.c_str() << '\'';
-       }
-       else {
-               static_cast<ostream&>(o) << in.c_str();
-       }
+               o.write(in.data(), in.length());
+       }
+       else if (in.escape_q()) {
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+
+               if (in.quote_q()) o.write("'", 1);
+               o.write(s, len);
+               if (in.quote_q()) o.write("'", 1);
+
+               delete[] s;
+       }
+       else {
+               if (in.quote_q()) o.write("'", 1);
+               o.write(in.data(), in.length());
+               if (in.quote_q()) o.write("'", 1);
+       }
+
        return o;
 }
 
@@ -328,12 +340,10 @@
 template <>
 ostream& operator <<(quote_only_type1 o, const ColData_Tmpl<string>& in)
 {
-       if (in.quote_q()) {
-               *o.ostr << '\'' << in.c_str() << '\'';
-       }
-       else {
-               *o.ostr << in.c_str();
-       }
+       if (in.quote_q()) o.ostr->write("'", 1);
+       o.ostr->write(in.data(), in.length());
+       if (in.quote_q()) o.ostr->write("'", 1);
+
        return *o.ostr;
 }
 
@@ -347,12 +357,10 @@
 ostream& operator <<(quote_only_type1 o,
                const ColData_Tmpl<const_string>& in)
 {
-       if (in.quote_q()) {
-               *o.ostr << '\'' << in.c_str() << '\'';
-       }
-       else {
-               *o.ostr << in.c_str();
-       }
+       if (in.quote_q()) o.ostr->write("'", 1);
+       o.ostr->write(in.data(), in.length());
+       if (in.quote_q()) o.ostr->write("'", 1);
+
        return *o.ostr;
 }
 
@@ -388,12 +396,10 @@
 ostream& operator <<(quote_double_only_type1 o,
                const ColData_Tmpl<string>& in)
 {
-       if (in.quote_q()) {
-               *o.ostr << '\'' << in.c_str() << '\'';
-       }
-       else {
-               *o.ostr << in.c_str();
-       }
+       if (in.quote_q()) o.ostr->write("\"", 1);
+       o.ostr->write(in.data(), in.length());
+       if (in.quote_q()) o.ostr->write("\"", 1);
+
        return *o.ostr;
 }
 
@@ -408,25 +414,24 @@
 ostream& operator <<(quote_double_only_type1 o,
                const ColData_Tmpl<const_string>& in)
 {
-       if (in.quote_q()) {
-               *o.ostr << '\'' << in.c_str() << '\'';
-       }
-       else {
-               *o.ostr << in.c_str();
-       }
+       if (in.quote_q()) o.ostr->write("'", 1);
+       o.ostr->write(in.data(), in.length());
+       if (in.quote_q()) o.ostr->write("'", 1);
+
        return *o.ostr;
 }
 
 
 SQLQueryParms& operator <<(escape_type2 p, SQLString& in)
 {
-       if (in.is_string && ! in.dont_escape) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(), 
-                               static_cast<unsigned long>(in.size()));
-               SQLString in2(s);
+       if (in.is_string && !in.dont_escape) {
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+
+               SQLString in2(s, len);
                in2.processed = true;
                *p.qparms << in2;
+
                delete[] s;
                return *p.qparms;
        }
@@ -446,10 +451,9 @@
 template <>
 std::ostream& operator <<(escape_type1 o, const std::string& in)
 {
-       char* s = new char[in.size() * 2 + 1];
-       mysql_escape_string(s, in.c_str(),
-                       static_cast<unsigned long>(in.size()));
-       *o.ostr << s;
+       char* s = new char[in.length() * 2 + 1];
+       size_t len = mysql_escape_string(s, in.data(), in.length());
+       o.ostr->write(s, len);
        delete[] s;
        return *o.ostr;
 }
@@ -465,10 +469,10 @@
 template <>
 ostream& operator <<(escape_type1 o, const char* const& in)
 {
-       size_t size = strlen(in);
-       char* s = new char[size * 2 + 1];
-       mysql_escape_string(s, in, static_cast<unsigned long>(size));
-       *o.ostr << s;
+       size_t len = strlen(in);
+       char* s = new char[len * 2 + 1];
+       len = mysql_escape_string(s, in, len);
+       o.ostr->write(s, len);
        delete[] s;
        return *o.ostr;
 }
@@ -480,14 +484,15 @@
 inline ostream& _manip(escape_type1 o, const ColData_Tmpl<Str>& in)
 {
        if (in.escape_q()) {
-               char* s = new char[in.size() * 2 + 1];
-               mysql_escape_string(s, in.c_str(),
-                               static_cast<unsigned long>(in.size()));
-               delete[] s;
-       }
-       else {
-               *o.ostr << in.c_str();
-       }
+               char* s = new char[in.length() * 2 + 1];
+               size_t len = mysql_escape_string(s, in.data(), in.length());
+               o.ostr->write(s, len);
+               delete[] s;
+       }
+       else {
+               o.ostr->write(in.data(), in.length());
+       }
+
        return *o.ostr;
 }
 


_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits

Reply via email to