Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Opencv
提交
a2445c44
O
Opencv
项目概览
Greenplum
/
Opencv
11 个月 前同步成功
通知
7
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Opencv
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a2445c44
编写于
5月 31, 2019
作者:
A
Alexander Alekhin
提交者:
Alexander Alekhin
6月 05, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
imgcodecs: sanitize PAM decoding
backporting of commit:
76fca0e7
上级
9802b4e1
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
118 addition
and
113 deletion
+118
-113
modules/imgcodecs/src/grfmt_pam.cpp
modules/imgcodecs/src/grfmt_pam.cpp
+118
-113
未找到文件。
modules/imgcodecs/src/grfmt_pam.cpp
浏览文件 @
a2445c44
...
...
@@ -56,7 +56,7 @@
#include "utils.hpp"
#include "grfmt_pam.hpp"
using
namespace
cv
;
namespace
cv
{
/* the PAM related fields */
#define MAX_PAM_HEADER_IDENITFIER_LENGTH 8
...
...
@@ -220,14 +220,14 @@ basic_conversion (void *src, const struct channel_layout *layout, int src_sampe_
}
static
bool
ReadPAMHeaderLine
(
cv
::
RLByteStream
&
strm
,
PamHeaderFieldType
&
fieldtype
,
char
value
[
MAX_PAM_HEADER_VALUE_LENGTH
+
1
])
static
bool
ReadPAMHeaderLine
(
cv
::
RLByteStream
&
strm
,
CV_OUT
PamHeaderFieldType
&
fieldtype
,
CV_OUT
char
value
[
MAX_PAM_HEADER_VALUE_LENGTH
+
1
])
{
int
code
,
pos
;
bool
ident_found
=
false
;
uint
i
;
char
ident
[
MAX_PAM_HEADER_IDENITFIER_LENGTH
+
1
]
=
{
0
};
int
code
;
char
ident
[
MAX_PAM_HEADER_IDENITFIER_LENGTH
+
1
]
=
{};
do
{
code
=
strm
.
getByte
();
...
...
@@ -246,82 +246,95 @@ static bool ReadPAMHeaderLine (cv::RLByteStream& strm,
return
true
;
}
/* nul-ify buffers before writing to them */
memset
(
ident
,
'\0'
,
sizeof
(
char
)
*
MAX_PAM_HEADER_IDENITFIER_LENGTH
);
for
(
i
=
0
;
i
<
MAX_PAM_HEADER_IDENITFIER_LENGTH
;
i
++
)
{
if
(
!
isspace
(
code
))
ident
[
i
]
=
(
char
)
code
;
else
int
ident_sz
=
0
;
for
(;
ident_sz
<
MAX_PAM_HEADER_IDENITFIER_LENGTH
;
ident_sz
++
)
{
if
(
isspace
(
code
))
break
;
ident
[
ident_sz
]
=
(
char
)
code
;
code
=
strm
.
getByte
();
}
CV_DbgAssert
(
ident_sz
<=
MAX_PAM_HEADER_IDENITFIER_LENGTH
);
ident
[
ident_sz
]
=
0
;
/* we may have filled the buffer and still have data */
if
(
!
isspace
(
code
))
return
false
;
for
(
i
=
0
;
i
<
PAM_FIELDS_NO
;
i
++
)
{
if
(
strncmp
(
fields
[
i
].
identifier
,
ident
,
MAX_PAM_HEADER_IDENITFIER_LENGTH
+
1
)
==
0
)
{
bool
ident_found
=
false
;
for
(
uint
i
=
0
;
i
<
PAM_FIELDS_NO
;
i
++
)
{
if
(
0
==
strncmp
(
fields
[
i
].
identifier
,
ident
,
std
::
min
(
ident_sz
,
MAX_PAM_HEADER_IDENITFIER_LENGTH
)
+
1
))
{
fieldtype
=
fields
[
i
].
type
;
ident_found
=
true
;
break
;
}
}
if
(
!
ident_found
)
return
false
;
memset
(
value
,
'\0'
,
sizeof
(
char
)
*
MAX_PAM_HEADER_VALUE_LENGTH
);
memset
(
value
,
0
,
sizeof
(
char
)
*
(
MAX_PAM_HEADER_VALUE_LENGTH
+
1
)
);
/* we may have an identifier that has no value */
if
(
code
==
'\n'
||
code
==
'\r'
)
return
true
;
do
{
code
=
strm
.
getByte
();
}
while
(
isspace
(
code
)
);
}
while
(
isspace
(
code
));
/* read identifier value */
for
(
i
=
0
;
i
<
MAX_PAM_HEADER_VALUE_LENGTH
;
i
++
)
{
if
(
code
!=
'\n'
&&
code
!=
'\r'
)
{
value
[
i
]
=
(
char
)
code
;
}
else
if
(
code
!=
'\n'
||
code
!
=
'\r'
)
int
value_sz
=
0
;
for
(;
value_sz
<
MAX_PAM_HEADER_VALUE_LENGTH
;
value_sz
++
)
{
if
(
code
==
'\n'
||
code
=
=
'\r'
)
break
;
value
[
value_sz
]
=
(
char
)
code
;
code
=
strm
.
getByte
();
}
pos
=
i
;
CV_DbgAssert
(
value_sz
<=
MAX_PAM_HEADER_VALUE_LENGTH
);
value
[
value_sz
]
=
0
;
int
pos
=
value_sz
;
/* should be terminated */
if
(
code
!=
'\n'
&&
code
!=
'\r'
)
return
false
;
/* remove trailing white spaces */
while
(
pos
>=
0
&&
isspace
(
value
[
pos
]))
value
[
pos
--
]
=
'\0'
;
while
(
--
pos
>=
0
&&
isspace
(
value
[
pos
]))
value
[
pos
]
=
0
;
return
true
;
}
static
bool
ParseNumber
(
char
*
str
,
int
*
retval
)
static
int
ParseInt
(
const
char
*
str
,
int
len
)
{
char
*
endptr
;
long
lval
=
strtol
(
str
,
&
endptr
,
0
);
if
((
errno
==
ERANGE
&&
(
lval
==
LONG_MAX
||
lval
==
LONG_MIN
))
||
(
errno
!=
0
&&
lval
==
0
))
{
return
false
;
}
if
(
endptr
==
str
)
{
return
false
;
}
*
retval
=
(
int
)
lval
;
CV_Assert
(
len
>
0
);
return
true
;
int
pos
=
0
;
bool
is_negative
=
false
;
if
(
str
[
0
]
==
'-'
)
{
is_negative
=
true
;
pos
++
;
CV_Assert
(
isdigit
(
str
[
pos
]));
}
uint64_t
number
=
0
;
while
(
pos
<
len
&&
isdigit
(
str
[
pos
]))
{
char
ch
=
str
[
pos
];
number
=
(
number
*
10
)
+
(
uint64_t
)((
int
)
ch
-
(
int
)
'0'
);
CV_Assert
(
number
<
INT_MAX
);
pos
++
;
}
if
(
pos
<
len
)
CV_Assert
(
str
[
pos
]
==
0
);
return
(
is_negative
)
?
-
(
int
)
number
:
(
int
)
number
;
}
namespace
cv
{
PAMDecoder
::
PAMDecoder
()
{
...
...
@@ -357,21 +370,12 @@ ImageDecoder PAMDecoder::newDecoder() const
return
makePtr
<
PAMDecoder
>
();
}
struct
parsed_fields
{
bool
endhdr
,
height
,
width
,
depth
,
maxval
;
};
#define HEADER_READ_CORRECT(pf) (pf.endhdr && pf.height && pf.width \
&& pf.depth && pf.maxval)
bool
PAMDecoder
::
readHeader
()
bool
PAMDecoder
::
readHeader
()
{
PamHeaderFieldType
fieldtype
=
PAM_HEADER_NONE
;
char
value
[
MAX_PAM_HEADER_VALUE_LENGTH
+
1
];
int
byte
;
struct
parsed_fields
flds
;
if
(
!
m_buf
.
empty
()
)
{
if
(
!
m_strm
.
open
(
m_buf
)
)
...
...
@@ -379,6 +383,7 @@ bool PAMDecoder::readHeader()
}
else
if
(
!
m_strm
.
open
(
m_filename
))
return
false
;
try
{
byte
=
m_strm
.
getByte
();
...
...
@@ -393,70 +398,72 @@ bool PAMDecoder::readHeader()
if
(
byte
!=
'\n'
&&
byte
!=
'\r'
)
throw
RBS_BAD_HEADER
;
uint
i
;
memset
(
&
flds
,
0x00
,
sizeof
(
struct
parsed_fields
));
bool
flds_endhdr
=
false
,
flds_height
=
false
,
flds_width
=
false
,
flds_depth
=
false
,
flds_maxval
=
false
;
do
{
if
(
!
ReadPAMHeaderLine
(
m_strm
,
fieldtype
,
value
))
throw
RBS_BAD_HEADER
;
switch
(
fieldtype
)
{
switch
(
fieldtype
)
{
case
PAM_HEADER_NONE
:
case
PAM_HEADER_COMMENT
:
continue
;
case
PAM_HEADER_ENDHDR
:
flds
.
endhdr
=
true
;
flds
_
endhdr
=
true
;
break
;
case
PAM_HEADER_HEIGHT
:
if
(
flds
.
height
)
throw
RBS_BAD_HEADER
;
if
(
!
ParseNumber
(
value
,
&
m_height
))
if
(
flds_height
)
throw
RBS_BAD_HEADER
;
flds
.
height
=
true
;
m_height
=
ParseInt
(
value
,
MAX_PAM_HEADER_VALUE_LENGTH
);
flds_height
=
true
;
break
;
case
PAM_HEADER_WIDTH
:
if
(
flds
.
width
)
if
(
flds
_
width
)
throw
RBS_BAD_HEADER
;
if
(
!
ParseNumber
(
value
,
&
m_width
))
throw
RBS_BAD_HEADER
;
flds
.
width
=
true
;
m_width
=
ParseInt
(
value
,
MAX_PAM_HEADER_VALUE_LENGTH
);
flds_width
=
true
;
break
;
case
PAM_HEADER_DEPTH
:
if
(
flds
.
depth
)
throw
RBS_BAD_HEADER
;
if
(
!
ParseNumber
(
value
,
&
m_channels
))
if
(
flds_depth
)
throw
RBS_BAD_HEADER
;
flds
.
depth
=
true
;
m_channels
=
ParseInt
(
value
,
MAX_PAM_HEADER_VALUE_LENGTH
);
flds_depth
=
true
;
break
;
case
PAM_HEADER_MAXVAL
:
if
(
flds
.
maxval
)
throw
RBS_BAD_HEADER
;
if
(
!
ParseNumber
(
value
,
&
m_maxval
))
if
(
flds_maxval
)
throw
RBS_BAD_HEADER
;
m_maxval
=
ParseInt
(
value
,
MAX_PAM_HEADER_VALUE_LENGTH
);
if
(
m_maxval
>
65535
)
throw
RBS_BAD_HEADER
;
if
(
m_maxval
>
255
)
{
m_sampledepth
=
CV_16U
;
}
else
m_sampledepth
=
CV_8U
;
m_sampledepth
=
(
m_maxval
>
255
)
?
CV_16U
:
CV_8U
;
if
(
m_maxval
==
1
)
bit_mode
=
true
;
flds
.
maxval
=
true
;
flds
_
maxval
=
true
;
break
;
case
PAM_HEADER_TUPLTYPE
:
for
(
i
=
0
;
i
<
PAM_FORMATS_NO
;
i
++
)
{
if
(
strncmp
(
formats
[
i
].
name
,
value
,
MAX_PAM_HEADER_VALUE_LENGTH
+
1
)
==
0
)
{
{
bool
format_found
=
false
;
for
(
uint
i
=
0
;
i
<
PAM_FORMATS_NO
;
i
++
)
{
if
(
0
==
strncmp
(
formats
[
i
].
name
,
value
,
MAX_PAM_HEADER_VALUE_LENGTH
+
1
))
{
selected_fmt
=
formats
[
i
].
fmt
;
format_found
=
true
;
break
;
}
}
CV_Assert
(
format_found
);
break
;
}
default:
throw
RBS_BAD_HEADER
;
}
}
while
(
fieldtype
!=
PAM_HEADER_ENDHDR
);
if
(
HEADER_READ_CORRECT
(
flds
))
{
if
(
selected_fmt
==
CV_IMWRITE_PAM_FORMAT_NULL
)
{
if
(
flds_endhdr
&&
flds_height
&&
flds_width
&&
flds_depth
&&
flds_maxval
)
{
if
(
selected_fmt
==
CV_IMWRITE_PAM_FORMAT_NULL
)
{
if
(
m_channels
==
1
&&
m_maxval
==
1
)
selected_fmt
=
CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE
;
else
if
(
m_channels
==
1
&&
m_maxval
<
256
)
...
...
@@ -469,28 +476,32 @@ bool PAMDecoder::readHeader()
return
true
;
}
}
catch
(...)
// failed
m_offset
=
-
1
;
m_width
=
m_height
=
-
1
;
m_strm
.
close
();
return
false
;
}
catch
(...)
{
m_offset
=
-
1
;
m_width
=
m_height
=
-
1
;
m_strm
.
close
();
throw
;
}
m_offset
=
-
1
;
m_width
=
m_height
=
-
1
;
m_strm
.
close
();
return
false
;
}
bool
PAMDecoder
::
readData
(
Mat
&
img
)
bool
PAMDecoder
::
readData
(
Mat
&
img
)
{
uchar
*
data
=
img
.
ptr
();
int
target_channels
=
img
.
channels
();
const
int
target_channels
=
img
.
channels
();
size_t
imp_stride
=
img
.
step
;
int
sample_depth
=
CV_ELEM_SIZE1
(
m_type
);
int
src_elems_per_row
=
m_width
*
m_channels
;
int
src_stride
=
src_elems_per_row
*
sample_depth
;
int
x
,
y
;
bool
res
=
false
,
funcout
;
PaletteEntry
palette
[
256
];
const
int
sample_depth
=
CV_ELEM_SIZE1
(
m_type
);
const
int
src_elems_per_row
=
m_width
*
m_channels
;
const
int
src_stride
=
src_elems_per_row
*
sample_depth
;
PaletteEntry
palette
[
256
]
=
{};
const
struct
pam_format
*
fmt
=
NULL
;
struct
channel_layout
layout
=
{
0
,
0
,
0
,
0
};
// normalized to 1-channel grey format
...
...
@@ -512,7 +523,6 @@ bool PAMDecoder::readData( Mat& img )
}
}
try
{
m_strm
.
setPos
(
m_offset
);
...
...
@@ -521,10 +531,10 @@ bool PAMDecoder::readData( Mat& img )
/* special case for 16bit images with wrong endianness */
if
(
m_sampledepth
==
CV_16U
&&
!
isBigEndian
())
{
for
(
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
for
(
int
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
{
m_strm
.
getBytes
(
src
,
src_stride
);
for
(
x
=
0
;
x
<
src_elems_per_row
;
x
++
)
for
(
int
x
=
0
;
x
<
src_elems_per_row
;
x
++
)
{
uchar
v
=
src
[
x
*
2
];
data
[
x
*
2
]
=
src
[
x
*
2
+
1
];
...
...
@@ -543,7 +553,7 @@ bool PAMDecoder::readData( Mat& img )
if
(
target_channels
==
1
)
{
uchar
gray_palette
[
2
]
=
{
0
,
255
};
for
(
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
for
(
int
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
{
m_strm
.
getBytes
(
src
,
src_stride
);
FillGrayRow1
(
data
,
src
,
m_width
,
gray_palette
);
...
...
@@ -551,21 +561,21 @@ bool PAMDecoder::readData( Mat& img )
}
else
if
(
target_channels
==
3
)
{
FillGrayPalette
(
palette
,
1
,
false
);
for
(
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
for
(
int
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
{
m_strm
.
getBytes
(
src
,
src_stride
);
FillColorRow1
(
data
,
src
,
m_width
,
palette
);
}
}
}
else
{
for
(
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
for
(
int
y
=
0
;
y
<
m_height
;
y
++
,
data
+=
imp_stride
)
{
m_strm
.
getBytes
(
src
,
src_stride
);
/* endianness correction */
if
(
m_sampledepth
==
CV_16U
&&
!
isBigEndian
()
)
{
for
(
x
=
0
;
x
<
src_elems_per_row
;
x
++
)
for
(
int
x
=
0
;
x
<
src_elems_per_row
;
x
++
)
{
uchar
v
=
src
[
x
*
2
];
src
[
x
*
2
]
=
src
[
x
*
2
+
1
];
...
...
@@ -576,7 +586,7 @@ bool PAMDecoder::readData( Mat& img )
/* scale down */
if
(
img
.
depth
()
==
CV_8U
&&
m_sampledepth
==
CV_16U
)
{
for
(
x
=
0
;
x
<
src_elems_per_row
;
x
++
)
for
(
int
x
=
0
;
x
<
src_elems_per_row
;
x
++
)
{
int
v
=
((
ushort
*
)
src
)[
x
];
src
[
x
]
=
(
uchar
)(
v
>>
8
);
...
...
@@ -589,7 +599,7 @@ bool PAMDecoder::readData( Mat& img )
}
/* perform correct conversion based on format */
else
if
(
fmt
)
{
funcout
=
false
;
bool
funcout
=
false
;
if
(
fmt
->
cvt_func
)
funcout
=
fmt
->
cvt_func
(
src
,
data
,
m_width
,
target_channels
,
img
.
depth
());
...
...
@@ -608,13 +618,8 @@ bool PAMDecoder::readData( Mat& img )
}
}
}
res
=
true
;
}
catch
(...)
{
}
return
res
;
return
true
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录