mirror of
https://github.com/fltk/fltk.git
synced 2026-05-30 21:25:30 +08:00
Fix for STR#3421: Fl_SVG_Image crashes if passed an svg file that is a static const char* string
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12536 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
+60
-2
@@ -43,6 +43,64 @@ struct NSVGimage;
|
|||||||
|
|
||||||
The FLTK library can optionally be built without SVG support; in that case,
|
The FLTK library can optionally be built without SVG support; in that case,
|
||||||
class Fl_SVG_Image is unavailable.
|
class Fl_SVG_Image is unavailable.
|
||||||
|
|
||||||
|
Example of displaying a hard-coded svg file:
|
||||||
|
\code
|
||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <FL/Fl_Window.H>
|
||||||
|
#include <FL/Fl_Box.H>
|
||||||
|
#include <FL/Fl_SVG_Image.H>
|
||||||
|
|
||||||
|
// A black rotated rectangle
|
||||||
|
const char *svg_data = "<svg viewBox=\"0 0 200 200\" version = \"1.1\">\n"
|
||||||
|
"<rect x=\"25\" y=\"50\" width=\"150\" height=\"100\" fill=\"black\" "
|
||||||
|
"transform=\"rotate(45 100 100)\"> </svg>\n";
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
Fl_SVG_Image *svg = new Fl_SVG_Image(0, svg_data); // create SVG object
|
||||||
|
Fl_Window *win = new Fl_Window(720, 486, "svg test");
|
||||||
|
Fl_Box *box = new Fl_Box(0,0,win->w(),win->h());
|
||||||
|
box->image(svg); // assign svg object to Fl_Box
|
||||||
|
win->end();
|
||||||
|
win->show(argc,argv);
|
||||||
|
return(Fl::run());
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Example of displaying an svg image from a file:
|
||||||
|
\code
|
||||||
|
#include <errno.h> // errno
|
||||||
|
#include <string.h> // strerror
|
||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <FL/Fl_Window.H>
|
||||||
|
#include <FL/Fl_Box.H>
|
||||||
|
#include <FL/Fl_SVG_Image.H>
|
||||||
|
#include <FL/fl_message.H>
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
Fl_Window *win = new Fl_Window(720, 486, "svg test");
|
||||||
|
Fl_Box *box = new Fl_Box(0,0,win->w(),win->h());
|
||||||
|
|
||||||
|
// Load svg image from disk, assign to a box
|
||||||
|
const char *svgpath = "/var/tmp/simple.svg";
|
||||||
|
Fl_SVG_Image *svg = new Fl_SVG_Image(svgpath); // load SVG object from disk
|
||||||
|
switch ( svg->fail() ) {
|
||||||
|
case Fl_Image::ERR_FILE_ACCESS:
|
||||||
|
// File couldn't load? show path + os error to user
|
||||||
|
fl_alert("%s: %s", svgpath, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
case Fl_Image::ERR_FORMAT:
|
||||||
|
// Parsing error
|
||||||
|
fl_alert("%s: couldn't decode image", svgpath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
box->image(svg); // assign svg object to box
|
||||||
|
|
||||||
|
win->end();
|
||||||
|
win->show(argc,argv);
|
||||||
|
return(Fl::run());
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
*/
|
*/
|
||||||
class FL_EXPORT Fl_SVG_Image : public Fl_RGB_Image {
|
class FL_EXPORT Fl_SVG_Image : public Fl_RGB_Image {
|
||||||
private:
|
private:
|
||||||
@@ -58,7 +116,7 @@ private:
|
|||||||
float average_weight_;
|
float average_weight_;
|
||||||
float svg_scaling_(int W, int H);
|
float svg_scaling_(int W, int H);
|
||||||
void rasterize_(int W, int H);
|
void rasterize_(int W, int H);
|
||||||
void init_(const char *filename, char *filedata, Fl_SVG_Image *copy_source);
|
void init_(const char *filename, const char *filedata, Fl_SVG_Image *copy_source);
|
||||||
Fl_SVG_Image(Fl_SVG_Image *source);
|
Fl_SVG_Image(Fl_SVG_Image *source);
|
||||||
protected:
|
protected:
|
||||||
virtual int draw_scaled(int X, int Y, int W, int H);
|
virtual int draw_scaled(int X, int Y, int W, int H);
|
||||||
@@ -66,7 +124,7 @@ public:
|
|||||||
/** Set this to \c false to allow image re-scaling that alters the image aspect ratio.
|
/** Set this to \c false to allow image re-scaling that alters the image aspect ratio.
|
||||||
Upon object creation, \c proportional is set to \c true, and the aspect ratio is kept constant.*/
|
Upon object creation, \c proportional is set to \c true, and the aspect ratio is kept constant.*/
|
||||||
bool proportional;
|
bool proportional;
|
||||||
Fl_SVG_Image(const char *filename, char *filedata = NULL);
|
Fl_SVG_Image(const char *filename, const char *filedata = NULL);
|
||||||
virtual ~Fl_SVG_Image();
|
virtual ~Fl_SVG_Image();
|
||||||
virtual Fl_Image *copy(int W, int H);
|
virtual Fl_Image *copy(int W, int H);
|
||||||
void resize(int width, int height);
|
void resize(int width, int height);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ int main(int argc, char **argv) {
|
|||||||
fl_message("You need to build fltk with --enable-nanosvg to use this example.");
|
fl_message("You need to build fltk with --enable-nanosvg to use this example.");
|
||||||
return(1);
|
return(1);
|
||||||
#else
|
#else
|
||||||
Fl_SVG_Image *svg = new Fl_SVG_Image(NULL, (char*)strdup(svg_logo)); // XXX: strdup() shouldn't be needed -- see STR #3421
|
Fl_SVG_Image *svg = new Fl_SVG_Image(NULL, svg_logo);
|
||||||
Fl_Window *win = new Fl_Window(720, 486, "svg test");
|
Fl_Window *win = new Fl_Window(720, 486, "svg test");
|
||||||
Fl_Box *box = new Fl_Box(10,10,720-20,486-20);
|
Fl_Box *box = new Fl_Box(10,10,720-20,486-20);
|
||||||
box->image(svg);
|
box->image(svg);
|
||||||
|
|||||||
+10
-8
@@ -48,9 +48,9 @@ static double strtoll(const char *str, char **endptr, int base) {
|
|||||||
\param filename A full path and name pointing to a .svg or .svgz file, or NULL.
|
\param filename A full path and name pointing to a .svg or .svgz file, or NULL.
|
||||||
\param filedata A pointer to the memory location of the SVG image data.
|
\param filedata A pointer to the memory location of the SVG image data.
|
||||||
This parameter allows to load an SVG image from in-memory data, and is used when \p filename is NULL.
|
This parameter allows to load an SVG image from in-memory data, and is used when \p filename is NULL.
|
||||||
\note In-memory SVG data is modified by the object constructor and is no longer used after construction.
|
\note In-memory SVG data is parsed by the object constructor and is no longer used after construction.
|
||||||
*/
|
*/
|
||||||
Fl_SVG_Image::Fl_SVG_Image(const char *filename, char *filedata) : Fl_RGB_Image(NULL, 0, 0, 4) {
|
Fl_SVG_Image::Fl_SVG_Image(const char *filename, const char *filedata) : Fl_RGB_Image(NULL, 0, 0, 4) {
|
||||||
init_(filename, filedata, NULL);
|
init_(filename, filedata, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,9 +113,9 @@ static char *svg_inflate(const char *fname) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *copy_source) {
|
void Fl_SVG_Image::init_(const char *filename, const char *in_filedata, Fl_SVG_Image *copy_source) {
|
||||||
if (copy_source) {
|
if (copy_source) {
|
||||||
filename = filedata = NULL;
|
filename = in_filedata = NULL;
|
||||||
counted_svg_image_ = copy_source->counted_svg_image_;
|
counted_svg_image_ = copy_source->counted_svg_image_;
|
||||||
counted_svg_image_->ref_count++;
|
counted_svg_image_->ref_count++;
|
||||||
} else {
|
} else {
|
||||||
@@ -123,6 +123,7 @@ void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *cop
|
|||||||
counted_svg_image_->svg_image = NULL;
|
counted_svg_image_->svg_image = NULL;
|
||||||
counted_svg_image_->ref_count = 1;
|
counted_svg_image_->ref_count = 1;
|
||||||
}
|
}
|
||||||
|
char *filedata = NULL;
|
||||||
to_desaturate_ = false;
|
to_desaturate_ = false;
|
||||||
average_weight_ = 1;
|
average_weight_ = 1;
|
||||||
proportional = true;
|
proportional = true;
|
||||||
@@ -130,7 +131,6 @@ void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *cop
|
|||||||
#if defined(HAVE_LIBZ)
|
#if defined(HAVE_LIBZ)
|
||||||
filedata = svg_inflate(filename);
|
filedata = svg_inflate(filename);
|
||||||
#else
|
#else
|
||||||
filedata = NULL;
|
|
||||||
FILE *fp = fl_fopen(filename, "rb");
|
FILE *fp = fl_fopen(filename, "rb");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
@@ -140,8 +140,7 @@ void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *cop
|
|||||||
if (filedata) {
|
if (filedata) {
|
||||||
if (fread(filedata, 1, size, fp) == size) {
|
if (fread(filedata, 1, size, fp) == size) {
|
||||||
filedata[size] = '\0';
|
filedata[size] = '\0';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
free(filedata);
|
free(filedata);
|
||||||
filedata = NULL;
|
filedata = NULL;
|
||||||
}
|
}
|
||||||
@@ -150,10 +149,13 @@ void Fl_SVG_Image::init_(const char *filename, char *filedata, Fl_SVG_Image *cop
|
|||||||
}
|
}
|
||||||
#endif // HAVE_LIBZ
|
#endif // HAVE_LIBZ
|
||||||
if (!filedata) ld(ERR_FILE_ACCESS);
|
if (!filedata) ld(ERR_FILE_ACCESS);
|
||||||
|
} else {
|
||||||
|
// XXX: Make internal copy -- nsvgParse() modifies filedata during parsing (!)
|
||||||
|
filedata = in_filedata ? strdup(in_filedata) : NULL;
|
||||||
}
|
}
|
||||||
if (filedata) {
|
if (filedata) {
|
||||||
counted_svg_image_->svg_image = nsvgParse(filedata, "px", 96);
|
counted_svg_image_->svg_image = nsvgParse(filedata, "px", 96);
|
||||||
if (filename) free(filedata);
|
free(filedata); // made with svg_inflate|malloc|strdup
|
||||||
if (counted_svg_image_->svg_image->width == 0 || counted_svg_image_->svg_image->height == 0) {
|
if (counted_svg_image_->svg_image->width == 0 || counted_svg_image_->svg_image->height == 0) {
|
||||||
d(-1);
|
d(-1);
|
||||||
ld(ERR_FORMAT);
|
ld(ERR_FORMAT);
|
||||||
|
|||||||
Reference in New Issue
Block a user