Coverage Report

Created: 2020-11-21 08:34

/src/botan/src/lib/base/scan_name.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* SCAN Name Abstraction
3
* (C) 2008-2009,2015 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/scan_name.h>
9
#include <botan/internal/parsing.h>
10
#include <botan/exceptn.h>
11
12
namespace Botan {
13
14
namespace {
15
16
std::string make_arg(const std::vector<std::pair<size_t, std::string>>& name, size_t start)
17
79.0k
   {
18
79.0k
   std::string output = name[start].second;
19
79.0k
   size_t level = name[start].first;
20
21
79.0k
   size_t paren_depth = 0;
22
23
79.0k
   for(size_t i = start + 1; i != name.size(); ++i)
24
1.11k
      {
25
1.11k
      if(name[i].first <= name[start].first)
26
1.11k
         break;
27
28
0
      if(name[i].first > level)
29
0
         {
30
0
         output += "(" + name[i].second;
31
0
         ++paren_depth;
32
0
         }
33
0
      else if(name[i].first < level)
34
0
         {
35
0
         for (size_t j = name[i].first; j < level; j++) {
36
0
            output += ")";
37
0
            --paren_depth;
38
0
         }
39
0
         output += "," + name[i].second;
40
0
         }
41
0
      else
42
0
         {
43
0
         if(output[output.size() - 1] != '(')
44
0
            output += ",";
45
0
         output += name[i].second;
46
0
         }
47
48
0
      level = name[i].first;
49
0
      }
50
51
79.0k
   for(size_t i = 0; i != paren_depth; ++i)
52
0
      output += ")";
53
54
79.0k
   return output;
55
79.0k
   }
56
57
}
58
59
SCAN_Name::SCAN_Name(const char* algo_spec) : SCAN_Name(std::string(algo_spec))
60
0
   {
61
0
   }
62
63
SCAN_Name::SCAN_Name(std::string algo_spec) : m_orig_algo_spec(algo_spec), m_alg_name(), m_args(), m_mode_info()
64
95.8k
   { 
65
95.8k
   if(algo_spec.size() == 0)
66
0
      throw Invalid_Argument("Expected algorithm name, got empty string");
67
68
95.8k
   std::vector<std::pair<size_t, std::string>> name;
69
95.8k
   size_t level = 0;
70
95.8k
   std::pair<size_t, std::string> accum = std::make_pair(level, "");
71
72
95.8k
   const std::string decoding_error = "Bad SCAN name '" + algo_spec + "': ";
73
74
1.46M
   for(size_t i = 0; i != algo_spec.size(); ++i)
75
1.36M
      {
76
1.36M
      char c = algo_spec[i];
77
78
1.36M
      if(c == '/' || c == ',' || c == '(' || c == ')')
79
157k
         {
80
157k
         if(c == '(')
81
77.9k
            ++level;
82
79.0k
         else if(c == ')')
83
77.9k
            {
84
77.9k
            if(level == 0)
85
0
               throw Decoding_Error(decoding_error + "Mismatched parens");
86
77.9k
            --level;
87
77.9k
            }
88
89
157k
         if(c == '/' && level > 0)
90
0
            accum.second.push_back(c);
91
157k
         else
92
157k
            {
93
157k
            if(accum.second != "")
94
157k
               name.push_back(accum);
95
157k
            accum = std::make_pair(level, "");
96
157k
            }
97
157k
         }
98
1.20M
      else
99
1.20M
         accum.second.push_back(c);
100
1.36M
      }
101
102
95.8k
   if(accum.second != "")
103
17.8k
      name.push_back(accum);
104
105
95.8k
   if(level != 0)
106
0
      throw Decoding_Error(decoding_error + "Missing close paren");
107
108
95.8k
   if(name.size() == 0)
109
0
      throw Decoding_Error(decoding_error + "Empty name");
110
111
95.8k
   m_alg_name = name[0].second;
112
113
95.8k
   bool in_modes = false;
114
115
174k
   for(size_t i = 1; i != name.size(); ++i)
116
79.0k
      {
117
79.0k
      if(name[i].first == 0)
118
0
         {
119
0
         m_mode_info.push_back(make_arg(name, i));
120
0
         in_modes = true;
121
0
         }
122
79.0k
      else if(name[i].first == 1 && !in_modes)
123
79.0k
         m_args.push_back(make_arg(name, i));
124
79.0k
      }
125
95.8k
   }
126
127
std::string SCAN_Name::arg(size_t i) const
128
66.3k
   {
129
66.3k
   if(i >= arg_count())
130
0
      throw Invalid_Argument("SCAN_Name::arg " + std::to_string(i) +
131
0
                             " out of range for '" + to_string() + "'");
132
66.3k
   return m_args[i];
133
66.3k
   }
134
135
std::string SCAN_Name::arg(size_t i, const std::string& def_value) const
136
80
   {
137
80
   if(i >= arg_count())
138
0
      return def_value;
139
80
   return m_args[i];
140
80
   }
141
142
size_t SCAN_Name::arg_as_integer(size_t i, size_t def_value) const
143
2.24k
   {
144
2.24k
   if(i >= arg_count())
145
1.36k
      return def_value;
146
880
   return to_u32bit(m_args[i]);
147
880
   }
148
149
size_t SCAN_Name::arg_as_integer(size_t i) const
150
0
   {
151
0
   return to_u32bit(arg(i));
152
0
   }
153
154
}