lavu/opt: add escaping to av_opt_serialize
authorLukasz Marek <lukasz.m.luki2@gmail.com>
Tue, 25 Nov 2014 19:25:10 +0000 (20:25 +0100)
committerLukasz Marek <lukasz.m.luki2@gmail.com>
Fri, 28 Nov 2014 23:58:42 +0000 (00:58 +0100)
Signed-off-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
libavutil/opt.c
libavutil/opt.h
tests/ref/fate/opt

index 64ce896..d873bd2 100644 (file)
@@ -1846,6 +1846,13 @@ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
     uint8_t *buf;
     AVBPrint bprint;
     int ret, cnt = 0;
+    const char special_chars[] = {pairs_sep, key_val_sep, '\0'};
+
+    if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
+        pairs_sep == '\\' || key_val_sep == '\\') {
+        av_log(obj, AV_LOG_ERROR, "Invalid separator(s) found.");
+        return AVERROR(EINVAL);
+    }
 
     if (!obj || !buffer)
         return AVERROR(EINVAL);
@@ -1869,7 +1876,9 @@ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
         if (buf) {
             if (cnt++)
                 av_bprint_append_data(&bprint, &pairs_sep, 1);
-            av_bprintf(&bprint, "%s%c%s", o->name, key_val_sep, buf);
+            av_bprint_escape(&bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+            av_bprint_append_data(&bprint, &key_val_sep, 1);
+            av_bprint_escape(&bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
             av_freep(&buf);
         }
     }
@@ -1903,6 +1912,7 @@ typedef struct TestContext
     int64_t num64;
     float flt;
     double dbl;
+    char *escape;
 } TestContext;
 
 #define OFFSET(x) offsetof(TestContext, x)
@@ -1916,6 +1926,7 @@ static const AVOption test_options[]= {
 {"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {.i64 = 1},       0,        1                   },
 {"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 1},       0,        10                  },
 {"string",   "set string",     OFFSET(string),   AV_OPT_TYPE_STRING,   {.str = "default"}, CHAR_MIN, CHAR_MAX          },
+{"escape",   "set escape str", OFFSET(escape),   AV_OPT_TYPE_STRING,   {.str = "\\=,"}, CHAR_MIN, CHAR_MAX             },
 {"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {.i64 = 1},       0,        INT_MAX, 0, "flags" },
 {"cool",     "set cool flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_COOL}, INT_MIN,  INT_MAX, 0, "flags" },
 {"lame",     "set lame flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_LAME}, INT_MIN,  INT_MAX, 0, "flags" },
@@ -1960,6 +1971,7 @@ int main(void)
         printf("num=%d\n", test_ctx.num);
         printf("toggle=%d\n", test_ctx.toggle);
         printf("string=%s\n", test_ctx.string);
+        printf("escape=%s\n", test_ctx.escape);
         printf("flags=%d\n", test_ctx.flags);
         printf("rational=%d/%d\n", test_ctx.rational.num, test_ctx.rational.den);
         printf("video_rate=%d/%d\n", test_ctx.video_rate.num, test_ctx.video_rate.den);
index d611c9b..5fc8a9b 100644 (file)
@@ -879,6 +879,8 @@ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_fla
  *
  * Create a string containing object's serialized options.
  * Such string may be passed back to av_opt_set_from_string() in order to restore option values.
+ * A key/value or pairs separator occurring in the serialized value or
+ * name string are escaped through the av_escape() function.
  *
  * @param[in]  obj           AVClass object to serialize
  * @param[in]  opt_flags     serialize options with all the specified flags set (AV_OPT_FLAG)
@@ -888,6 +890,7 @@ int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_fla
  * @param[in]  key_val_sep   character used to separate key from value
  * @param[in]  pairs_sep     character used to separate two pairs from each other
  * @return                   >= 0 on success, negative on error
+ * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same.
  */
 int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
                      const char key_val_sep, const char pairs_sep);
index 16f3387..084a222 100644 (file)
@@ -2,6 +2,7 @@ Testing default values
 num=0
 toggle=1
 string=default
+escape=\=,
 flags=1
 rational=1/1
 video_rate=25/1
@@ -22,6 +23,7 @@ name:       num default:1 error:
 name:    toggle default:0 error:
 name:  rational default:0 error:
 name:    string default:0 error:
+name:    escape default:0 error:
 name:     flags default:0 error:
 name:      cool default:1 error:Option not found
 name:      lame default:1 error:Option not found
@@ -43,6 +45,7 @@ name:       num default:1 error:
 name:    toggle default:1 error:
 name:  rational default:1 error:
 name:    string default:1 error:
+name:    escape default:1 error:
 name:     flags default:1 error:
 name:      cool default:1 error:Option not found
 name:      lame default:1 error:Option not found
@@ -62,8 +65,8 @@ name:       flt default:1 error:
 name:       dbl default:1 error:
 
 Test av_opt_serialize()
-num=0,toggle=1,rational=1/1,string=default,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
-num=0,toggle=1,rational=1/1,string=default,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
+num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
+num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
 
 Testing av_set_options_string()
 OK    ''